Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions noir-projects/aztec-nr/aztec/src/macros/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ pub(crate) comptime fn add_to_hasher(hasher_name: Quoted, name: Quoted, typ: Typ
$hasher_name.add_multiple($serialized_name[i]);
}
}
} else if typ.as_tuple().is_some() {
let tuple_len = typ.as_tuple().unwrap().len();
let mut tuple_quotes: [Quoted] = [];
for i in 0..tuple_len {
let element_quote = quote { $hasher_name.add_multiple(dep::aztec::protocol_types::traits::Serialize::serialize($name.$i)); };
tuple_quotes = tuple_quotes.push_back(element_quote);
}
tuple_quotes.join(quote {})
} else if typ.as_str().is_some() {
quote {
$hasher_name.add_multiple($name.as_bytes().map(| byte: u8 | byte as Field));
Expand Down
1 change: 1 addition & 0 deletions noir-projects/noir-contracts/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ members = [
"contracts/test/note_getter_contract",
"contracts/test/parent_contract",
"contracts/test/pending_note_hashes_contract",
"contracts/test/returning_tuple_contract",
"contracts/test/spam_contract",
"contracts/test/state_vars_contract",
"contracts/test/stateful_test_contract",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "returning_tuple_contract"
authors = [""]
compiler_version = ">=0.25.0"
type = "contract"

[dependencies]
aztec = { path = "../../../../aztec-nr/aztec" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use aztec::macros::aztec;

// Tests that Aztec.nr handles returning tuples correctly.
#[aztec]
pub contract ReturningTuple {
Comment thread
benesjan marked this conversation as resolved.
use aztec::{
macros::functions::{private, view},
prelude::{AztecAddress, Point},
protocol_types::traits::{Deserialize, FromField},
};

#[private]
#[view]
fn fn_that_returns_1() -> (bool,) {
(true,)
}

#[private]
#[view]
fn fn_that_returns_2() -> (Field, u32) {
(1, 2)
}

#[private]
#[view]
fn fn_that_returns_3() -> (Field, bool, str<4>) {
(1, true, "test")
}

#[private]
#[view]
fn fn_that_returns_4() -> (Field, u64, bool, str<3>) {
(1, 2, false, "abc")
}

#[private]
#[view]
fn fn_that_returns_5() -> (Field, u32, bool, str<2>, i64) {
(1, 2, true, "hi", -5)
}

#[private]
#[view]
fn fn_that_returns_6() -> (Field, u128, bool, str<3>, AztecAddress, Point) {
(1, 2, false, "xyz", AztecAddress::from_field(1), Point::deserialize([1, 2, 3]))
}
}
87 changes: 87 additions & 0 deletions yarn-project/stdlib/src/abi/decoder.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Fr } from '@aztec/foundation/fields';

import { AztecAddress } from '../aztec-address/index.js';
import type { ABIParameterVisibility, FunctionArtifact } from './abi.js';
import { decodeFromAbi, decodeFunctionSignature, decodeFunctionSignatureWithParameterNames } from './decoder.js';

Expand Down Expand Up @@ -182,4 +183,90 @@ describe('decoder', () => {
);
expect(decoded).toBe(2n ** 63n - 1n);
});

it('decodes a tuple', () => {
// ABI copied from noir-projects/noir-contracts/target/returning_tuple_contract-ReturningTuple.json
const decoded = decodeFromAbi(
[
{
kind: 'tuple',
fields: [
{
kind: 'field',
},
{
kind: 'integer',
sign: 'unsigned',
width: 128,
},
{
kind: 'boolean',
},
{
kind: 'string',
length: 3,
},
{
kind: 'struct',
path: 'aztec::protocol_types::address::aztec_address::AztecAddress',
fields: [
{
name: 'inner',
type: {
kind: 'field',
},
},
],
},
{
kind: 'struct',
path: 'std::embedded_curve_ops::EmbeddedCurvePoint',
fields: [
{
name: 'x',
type: {
kind: 'field',
},
},
{
name: 'y',
type: {
kind: 'field',
},
},
{
name: 'is_infinite',
type: {
kind: 'boolean',
},
},
],
},
],
},
],
[
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')), // field
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000002', 'hex')), // u128
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex')), // bool
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000078', 'hex')), // "x"
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000079', 'hex')), // "y"
Fr.fromBuffer(Buffer.from('000000000000000000000000000000000000000000000000000000000000007a', 'hex')), // "z"
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')), // address
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')), // point.x
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000002', 'hex')), // point.y
Fr.fromBuffer(Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex')), // point.is_infinite
],
);

expect(decoded).toEqual([
1n,
2n,
false,
'xyz',
AztecAddress.fromBigInt(1n),
// eslint-disable-next-line camelcase
{ x: 1n, y: 2n, is_infinite: false },
]);
});
});
9 changes: 5 additions & 4 deletions yarn-project/stdlib/src/abi/decoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { isAztecAddressStruct, parseSignedInt } from './utils.js';
/**
* The type of our decoded ABI.
*/
export type AbiDecoded = bigint | boolean | AztecAddress | AbiDecoded[] | { [key: string]: AbiDecoded };
export type AbiDecoded = bigint | boolean | string | AztecAddress | AbiDecoded[] | { [key: string]: AbiDecoded };

/**
* Decodes values using a provided ABI.
Expand Down Expand Up @@ -58,11 +58,12 @@ class AbiDecoder {
return struct;
}
case 'string': {
const array = [];
let str = '';
for (let i = 0; i < abiType.length; i += 1) {
array.push(this.getNextField().toBigInt());
const charCode = Number(this.getNextField().toBigInt());
str += String.fromCharCode(charCode);
}
return array;
return str;
}
case 'tuple': {
const array = [];
Expand Down