Skip to content

Commit 945e381

Browse files
committed
test(avm): adding missing tests
1 parent 4e32634 commit 945e381

File tree

1 file changed

+228
-0
lines changed
  • barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzz_lib

1 file changed

+228
-0
lines changed

barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzz_lib/fuzz.test.cpp

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,3 +1646,231 @@ TEST(fuzz, StaticCallToNonStaticFunctionSuccessCopy)
16461646
EXPECT_EQ(result.reverted, false);
16471647
}
16481648
} // namespace external_calls
1649+
1650+
namespace crypto_ops {
1651+
1652+
TEST(fuzz, Poseidon2PermSmoke)
1653+
{
1654+
// Set up 4 FF values for Poseidon2 permutation input
1655+
std::vector<FuzzInstruction> instructions;
1656+
for (uint32_t i = 0; i < 4; i++) {
1657+
instructions.push_back(
1658+
SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1659+
.result_address = AddressRef{ .address = i, .mode = AddressingMode::Direct },
1660+
.value = FF(i + 1) });
1661+
}
1662+
// Poseidon2 permutation: reads from address 0-3, writes to address 10-13
1663+
instructions.push_back(
1664+
POSEIDON2PERM_Instruction{ .src_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1665+
.dst_address = AddressRef{ .address = 10, .mode = AddressingMode::Direct } });
1666+
1667+
auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1668+
auto control_flow = ControlFlow(instruction_blocks);
1669+
control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1670+
auto bytecode = control_flow.build_bytecode(
1671+
ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 });
1672+
1673+
auto result = simulate_with_default_tx(bytecode, {});
1674+
EXPECT_FALSE(result.reverted);
1675+
}
1676+
1677+
TEST(fuzz, Keccakf1600Smoke)
1678+
{
1679+
// Set up 25 U64 values for Keccak-f[1600] permutation input
1680+
std::vector<FuzzInstruction> instructions;
1681+
for (uint32_t i = 0; i < 25; i++) {
1682+
instructions.push_back(
1683+
SET_64_Instruction{ .value_tag = bb::avm2::MemoryTag::U64,
1684+
.result_address = AddressRef{ .address = i, .mode = AddressingMode::Direct },
1685+
.value = static_cast<uint64_t>(i + 1) });
1686+
}
1687+
// Keccak-f[1600]: reads from address 0-24, writes to address 100-124
1688+
instructions.push_back(
1689+
KECCAKF1600_Instruction{ .src_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1690+
.dst_address = AddressRef{ .address = 100, .mode = AddressingMode::Direct } });
1691+
1692+
auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1693+
auto control_flow = ControlFlow(instruction_blocks);
1694+
control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1695+
auto bytecode = control_flow.build_bytecode(ReturnOptions{
1696+
.return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U64, .return_value_offset_index = 25 });
1697+
1698+
auto result = simulate_with_default_tx(bytecode, {});
1699+
EXPECT_FALSE(result.reverted);
1700+
}
1701+
1702+
TEST(fuzz, Sha256CompressionSmoke)
1703+
{
1704+
// Set up 8 U32 values for state and 16 U32 values for input
1705+
std::vector<FuzzInstruction> instructions;
1706+
1707+
// State: addresses 0-7
1708+
for (uint32_t i = 0; i < 8; i++) {
1709+
instructions.push_back(
1710+
SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1711+
.result_address = AddressRef{ .address = i, .mode = AddressingMode::Direct },
1712+
.value = i + 1 });
1713+
}
1714+
// Input: addresses 20-35
1715+
for (uint32_t i = 0; i < 16; i++) {
1716+
instructions.push_back(
1717+
SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1718+
.result_address = AddressRef{ .address = 20 + i, .mode = AddressingMode::Direct },
1719+
.value = i + 100 });
1720+
}
1721+
// SHA256 compression: state at 0-7, input at 20-35, output at 50-57
1722+
instructions.push_back(
1723+
SHA256COMPRESSION_Instruction{ .state_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1724+
.input_address = AddressRef{ .address = 20, .mode = AddressingMode::Direct },
1725+
.dst_address = AddressRef{ .address = 50, .mode = AddressingMode::Direct } });
1726+
1727+
auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1728+
auto control_flow = ControlFlow(instruction_blocks);
1729+
control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1730+
auto bytecode = control_flow.build_bytecode(ReturnOptions{
1731+
.return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U32, .return_value_offset_index = 12 });
1732+
1733+
auto result = simulate_with_default_tx(bytecode, {});
1734+
EXPECT_FALSE(result.reverted);
1735+
}
1736+
1737+
TEST(fuzz, EcaddSmoke)
1738+
{
1739+
std::vector<FuzzInstruction> instructions;
1740+
1741+
// Use the generator point G = (1, sqrt(-16)) as p1
1742+
// For simplicity, we'll use infinity points which should work
1743+
// Set p1 as infinity: x=0, y=0, infinite=1
1744+
instructions.push_back(
1745+
SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1746+
.result_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1747+
.value = FF(0) }); // p1.x
1748+
instructions.push_back(
1749+
SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1750+
.result_address = AddressRef{ .address = 1, .mode = AddressingMode::Direct },
1751+
.value = FF(0) }); // p1.y
1752+
instructions.push_back(
1753+
SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
1754+
.result_address = AddressRef{ .address = 2, .mode = AddressingMode::Direct },
1755+
.value = 1 }); // p1.infinite = true
1756+
1757+
// Set p2 as infinity too
1758+
instructions.push_back(
1759+
SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1760+
.result_address = AddressRef{ .address = 3, .mode = AddressingMode::Direct },
1761+
.value = FF(0) }); // p2.x
1762+
instructions.push_back(
1763+
SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1764+
.result_address = AddressRef{ .address = 4, .mode = AddressingMode::Direct },
1765+
.value = FF(0) }); // p2.y
1766+
instructions.push_back(
1767+
SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
1768+
.result_address = AddressRef{ .address = 5, .mode = AddressingMode::Direct },
1769+
.value = 1 }); // p2.infinite = true
1770+
1771+
// ECADD instruction: infinity + infinity = infinity
1772+
instructions.push_back(ECADD_Instruction{ .p1_x = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1773+
.p1_y = AddressRef{ .address = 1, .mode = AddressingMode::Direct },
1774+
.p1_infinite = AddressRef{ .address = 2, .mode = AddressingMode::Direct },
1775+
.p2_x = AddressRef{ .address = 3, .mode = AddressingMode::Direct },
1776+
.p2_y = AddressRef{ .address = 4, .mode = AddressingMode::Direct },
1777+
.p2_infinite = AddressRef{ .address = 5, .mode = AddressingMode::Direct },
1778+
.result = AddressRef{ .address = 10, .mode = AddressingMode::Direct } });
1779+
1780+
auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1781+
auto control_flow = ControlFlow(instruction_blocks);
1782+
control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1783+
// Return the infinite flag of the result (should be 1)
1784+
auto bytecode = control_flow.build_bytecode(
1785+
ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 3 });
1786+
1787+
auto result = simulate_with_default_tx(bytecode, {});
1788+
EXPECT_FALSE(result.reverted);
1789+
}
1790+
1791+
} // namespace crypto_ops
1792+
1793+
namespace conversions {
1794+
1795+
TEST(fuzz, ToRadixBESmoke)
1796+
{
1797+
std::vector<FuzzInstruction> instructions;
1798+
1799+
// Set value to convert (FF)
1800+
instructions.push_back(
1801+
SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1802+
.result_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1803+
.value = FF(255) });
1804+
// Set radix (U32) = 2 (binary)
1805+
instructions.push_back(
1806+
SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1807+
.result_address = AddressRef{ .address = 1, .mode = AddressingMode::Direct },
1808+
.value = 2 });
1809+
// Set num_limbs (U32) = 8
1810+
instructions.push_back(
1811+
SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1812+
.result_address = AddressRef{ .address = 2, .mode = AddressingMode::Direct },
1813+
.value = 8 });
1814+
// Set output_bits (U1) = 1 (since radix is 2)
1815+
instructions.push_back(
1816+
SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
1817+
.result_address = AddressRef{ .address = 3, .mode = AddressingMode::Direct },
1818+
.value = 1 });
1819+
1820+
// TORADIXBE instruction
1821+
instructions.push_back(
1822+
TORADIXBE_Instruction{ .value_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1823+
.radix_address = AddressRef{ .address = 1, .mode = AddressingMode::Direct },
1824+
.num_limbs_address = AddressRef{ .address = 2, .mode = AddressingMode::Direct },
1825+
.output_bits_address = AddressRef{ .address = 3, .mode = AddressingMode::Direct },
1826+
.dst_address = AddressRef{ .address = 10, .mode = AddressingMode::Direct },
1827+
.is_output_bits = true });
1828+
1829+
auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1830+
auto control_flow = ControlFlow(instruction_blocks);
1831+
control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1832+
auto bytecode = control_flow.build_bytecode(
1833+
ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 2 });
1834+
1835+
auto result = simulate_with_default_tx(bytecode, {});
1836+
EXPECT_FALSE(result.reverted);
1837+
}
1838+
1839+
} // namespace conversions
1840+
1841+
namespace l1_l2_messaging {
1842+
1843+
TEST(fuzz, L1ToL2MsgExistsSmoke)
1844+
{
1845+
std::vector<FuzzInstruction> instructions;
1846+
1847+
// Set msg_hash (FF)
1848+
instructions.push_back(
1849+
SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1850+
.result_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1851+
.value = FF(12345) });
1852+
// Set leaf_index (U64)
1853+
instructions.push_back(
1854+
SET_64_Instruction{ .value_tag = bb::avm2::MemoryTag::U64,
1855+
.result_address = AddressRef{ .address = 1, .mode = AddressingMode::Direct },
1856+
.value = 0 });
1857+
1858+
// L1TOL2MSGEXISTS instruction - check if message exists (it won't, but shouldn't revert)
1859+
instructions.push_back(
1860+
L1TOL2MSGEXISTS_Instruction{ .msg_hash_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1861+
.leaf_index_address = AddressRef{ .address = 1, .mode = AddressingMode::Direct },
1862+
.result_address = AddressRef{ .address = 2, .mode = AddressingMode::Direct } });
1863+
1864+
auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1865+
auto control_flow = ControlFlow(instruction_blocks);
1866+
control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1867+
auto bytecode = control_flow.build_bytecode(
1868+
ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 0 });
1869+
1870+
auto result = simulate_with_default_tx(bytecode, {});
1871+
EXPECT_FALSE(result.reverted);
1872+
// Message doesn't exist, so result should be 0
1873+
EXPECT_EQ(result.output.at(0), FF::zero());
1874+
}
1875+
1876+
} // namespace l1_l2_messaging

0 commit comments

Comments
 (0)