Skip to content

Commit

Permalink
add syscall secp256k1
Browse files Browse the repository at this point in the history
  • Loading branch information
0x0ece committed May 16, 2024
1 parent dc80e8d commit 7224872
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 62 deletions.
4 changes: 2 additions & 2 deletions generators/secp256k1.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
# tested above
# https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L975-L978
# signature fails to decode
[1, 32, 0, 0, 12, 0, 0, 97, 0, 5, 0, 0, 129, 246, 169, 169, 105, 76, 208, 128, 223, 135, 27, 68, 249, 42, 201, 69, 55, 2, 173, 101, 255, 196, 198, 193, 237, 0, 14, 83, 87, 183, 25, 69, 136, 43, 251, 73, 44, 194, 141, 230, 102, 16, 220, 6, 46, 214, 214, 125, 120, 16, 103, 254, 39, 121, 88, 223, 156, 229, 186, 211, 38, 101, 196, 233, 125, 150, 136, 177, 123, 197, 48, 219, 28, 26, 10, 76, 198, 127, 91, 80, 88, 191, 6, 3, 255, 104, 101, 108, 108, 111],
# \--- pubkey (eth) ---/ \--- sig ---/ \--- msg ---/
[1, 32, 0, 0, 12, 0, 0, 97, 0, 5, 0, 0, 129, 246, 169, 169, 105, 76, 208, 128, 223, 135, 27, 68, 249, 42, 201, 69, 55, 2, 173, 101, 255, 196, 198, 193, 237, 0, 14, 83, 87, 183, 25, 69, 136, 43, 251, 73, 44, 194, 141, 230, 102, 16, 220, 6, 46, 214, 214, 125, 120, 16, 103, 254, 39, 121, 88, 223, 156, 229, 186, 211, 38, 101, 196, 233, 125, 150, 136, 177, 123, 197, 48, 219, 28, 26, 10, 76, 198, 127, 91, 80, 88, 191, 6, 3, 1, 104, 101, 108, 108, 111],
# \--- pubkey (eth) ---/ \--- sig ---/ \--- msg ---/

# InvalidRecoveryId (result: 2)
# https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L981C43-L981C60
Expand Down
44 changes: 22 additions & 22 deletions generators/syscalls_hash.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import hashlib
import test_suite.vm_pb2 as pbvm
from dataclasses import dataclass
import struct

OUTPUT_DIR = "./test-vectors/instr/inputs/20240425/syscalls"
Expand Down Expand Up @@ -179,30 +178,31 @@ def exact_cu_cost(data_vec):
def _into_key_data(key_prefix, test_vectors):
return [(key_prefix + str(j), data) for j, data in enumerate(test_vectors)]

print("Generating syscalls sha256, keccak256, blake3 tests...")

test_vectors = _into_key_data("h", test_vectors_hash)

for (key, test) in test_vectors:
for hash in ["sha256", "keccak256", "blake3"]:
heap_prefix = test.get("heap_prefix", [])
syscall_ctx = pbvm.SyscallContext()
syscall_ctx.syscall_invocation.function_name = bytes("sol_" + hash, "ascii")
syscall_ctx.syscall_invocation.heap_prefix = bytes(heap_prefix)
syscall_ctx.vm_ctx.heap_max = len(heap_prefix)
syscall_ctx.vm_ctx.r1 = test.get("vals_addr", 0)
syscall_ctx.vm_ctx.r2 = test.get("vals_len", 0)
syscall_ctx.vm_ctx.r3 = test.get("result_addr", 0)
syscall_ctx.instr_ctx.cu_avail = test.get("cu_avail", 0)
syscall_ctx.instr_ctx.program_id = bytes([0]*32) # solfuzz-agave expectes a program_id
syscall_ctx.vm_ctx.rodata = b"x" # fd expects some bytes
if __name__ == "__main__":
print("Generating syscalls sha256, keccak256, blake3 tests...")

for (key, test) in test_vectors:
for hash in ["sha256", "keccak256", "blake3"]:
heap_prefix = test.get("heap_prefix", [])
syscall_ctx = pbvm.SyscallContext()
syscall_ctx.syscall_invocation.function_name = bytes("sol_" + hash, "ascii")
syscall_ctx.syscall_invocation.heap_prefix = bytes(heap_prefix)
syscall_ctx.vm_ctx.heap_max = len(heap_prefix)
syscall_ctx.vm_ctx.r1 = test.get("vals_addr", 0)
syscall_ctx.vm_ctx.r2 = test.get("vals_len", 0)
syscall_ctx.vm_ctx.r3 = test.get("result_addr", 0)
syscall_ctx.instr_ctx.cu_avail = test.get("cu_avail", 0)
syscall_ctx.instr_ctx.program_id = bytes([0]*32) # solfuzz-agave expectes a program_id
syscall_ctx.vm_ctx.rodata = b"x" # fd expects some bytes

syscall_ctx.instr_ctx.epoch_context.features.features.extend([0xe994a4b8eeea84f4]) # enable blake3
syscall_ctx.instr_ctx.epoch_context.features.features.extend([0xe994a4b8eeea84f4]) # enable blake3

filename = str(key) + "_" + hashlib.sha3_256(syscall_ctx.instr_ctx.data).hexdigest()[:16]
filename = str(key) + "_" + hashlib.sha3_256(syscall_ctx.instr_ctx.data).hexdigest()[:16]

serialized_instr = syscall_ctx.SerializeToString(deterministic=True)
with open(f"{OUTPUT_DIR}/{hash}/{filename}.bin", "wb") as f:
f.write(serialized_instr)
serialized_instr = syscall_ctx.SerializeToString(deterministic=True)
with open(f"{OUTPUT_DIR}/{hash}/{filename}.bin", "wb") as f:
f.write(serialized_instr)

print("done!")
print("done!")
67 changes: 34 additions & 33 deletions generators/syscalls_poseidon.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import hashlib
import test_suite.vm_pb2 as pbvm
from dataclasses import dataclass
import struct
from syscalls_hash import test_vectors as test_vectors_hash, heap_vec

OUTPUT_DIR = "./test-vectors/instr/inputs/20240425/syscalls/poseidon"
Expand Down Expand Up @@ -190,34 +188,37 @@ def _into_key_data(key_prefix, test_vectors):
# these are all the tests in test_vectors_poseidon
]

print("Generating syscall poseidon tests...")

test_vectors = _into_key_data("p", test_vectors_poseidon) + _into_key_data("w", test_vectors_workflow) + test_vectors_hash

for (key, test) in test_vectors:
heap_prefix = test.get("heap_prefix", [])
syscall_ctx = pbvm.SyscallContext()
syscall_ctx.syscall_invocation.function_name = b"sol_poseidon"
syscall_ctx.syscall_invocation.heap_prefix = bytes(heap_prefix)
syscall_ctx.vm_ctx.heap_max = len(heap_prefix)
syscall_ctx.vm_ctx.r1 = test.get("params", 0)
syscall_ctx.vm_ctx.r2 = test.get("endianness", 0)
syscall_ctx.vm_ctx.r3 = test.get("vals_addr", 0)
syscall_ctx.vm_ctx.r4 = test.get("vals_len", 0)
syscall_ctx.vm_ctx.r5 = test.get("result_addr", 0)
syscall_ctx.instr_ctx.cu_avail = test.get("cu_avail", 0)
syscall_ctx.instr_ctx.program_id = bytes([0]*32) # solfuzz-agave expectes a program_id
syscall_ctx.vm_ctx.rodata = b"x" # fd expects some bytes

syscall_ctx.instr_ctx.epoch_context.features.features.extend([
0x3cbf822ccb2eebd4, # enable_poseidon_syscall
0x8ba9e9038d9fdcff, # simplify_alt_bn128_syscall_error_codes
])

filename = str(key) + "_" + hashlib.sha3_256(syscall_ctx.instr_ctx.data).hexdigest()[:16]

serialized_instr = syscall_ctx.SerializeToString(deterministic=True)
with open(f"{OUTPUT_DIR}/{filename}.bin", "wb") as f:
f.write(serialized_instr)

print("done!")
test_vectors = _into_key_data("p", test_vectors_poseidon) \
+ _into_key_data("w", test_vectors_workflow) \
+ test_vectors_hash

if __name__ == "__main__":
print("Generating syscall poseidon tests...")

for (key, test) in test_vectors:
heap_prefix = test.get("heap_prefix", [])
syscall_ctx = pbvm.SyscallContext()
syscall_ctx.syscall_invocation.function_name = b"sol_poseidon"
syscall_ctx.syscall_invocation.heap_prefix = bytes(heap_prefix)
syscall_ctx.vm_ctx.heap_max = len(heap_prefix)
syscall_ctx.vm_ctx.r1 = test.get("params", 0)
syscall_ctx.vm_ctx.r2 = test.get("endianness", 0)
syscall_ctx.vm_ctx.r3 = test.get("vals_addr", 0)
syscall_ctx.vm_ctx.r4 = test.get("vals_len", 0)
syscall_ctx.vm_ctx.r5 = test.get("result_addr", 0)
syscall_ctx.instr_ctx.cu_avail = test.get("cu_avail", 0)
syscall_ctx.instr_ctx.program_id = bytes([0]*32) # solfuzz-agave expectes a program_id
syscall_ctx.vm_ctx.rodata = b"x" # fd expects some bytes

syscall_ctx.instr_ctx.epoch_context.features.features.extend([
0x3cbf822ccb2eebd4, # enable_poseidon_syscall
# 0x8ba9e9038d9fdcff, # simplify_alt_bn128_syscall_error_codes
])

filename = str(key) + "_" + hashlib.sha3_256(syscall_ctx.instr_ctx.data).hexdigest()[:16]

serialized_instr = syscall_ctx.SerializeToString(deterministic=True)
with open(f"{OUTPUT_DIR}/{filename}.bin", "wb") as f:
f.write(serialized_instr)

print("done!")
206 changes: 206 additions & 0 deletions generators/syscalls_secp256k1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import hashlib
import test_suite.vm_pb2 as pbvm
from eth_hash.auto import keccak

OUTPUT_DIR = "./test-vectors/instr/inputs/20240425/syscalls/secp256k1"
HEAP_START = 0x300000000
CU_BASE = 25_000

def _into_key_data(key_prefix, test_vectors):
return [(key_prefix + str(j), data) for j, data in enumerate(test_vectors)]

pubkey = [129, 246, 169, 169, 105, 76, 208, 128, 223, 135, 27, 68, 249, 42, 201, 69, 55, 2, 173, 101]
sig = [14, 196, 198, 193, 237, 0, 14, 83, 87, 183, 25, 69, 136, 43, 251, 73, 44, 194, 141, 230, 102, 16, 220, 6, 46, 214, 214, 125, 120, 16, 103, 254, 39, 121, 88, 223, 156, 229, 186, 211, 38, 101, 196, 233, 125, 150, 136, 177, 123, 197, 48, 219, 28, 26, 10, 76, 198, 127, 91, 80, 88, 191, 6, 3]
sig_invalid = [255]*64
sig_err = [14, 196, 198, 193, 237, 0, 14, 255, 87, 183, 25, 69, 136, 43, 251, 73, 44, 194, 141, 230, 102, 16, 220, 6, 46, 214, 214, 125, 120, 16, 103, 254, 39, 121, 88, 223, 156, 229, 186, 211, 38, 101, 196, 233, 125, 150, 136, 177, 123, 197, 48, 219, 28, 26, 10, 76, 198, 127, 91, 80, 88, 191, 6, 3]
# ^^^ modified byte
recid = 1
msg = [104, 101, 108, 108, 111] # hello
hash = list(keccak(bytes(msg)))

# all these tests either return Err(.)
test_vectors_workflow = [
# valid
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
{
"heap_prefix": sig + hash,
"hash_vaddr": HEAP_START + 64,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
{
"heap_prefix": hash + sig,
"hash_vaddr": HEAP_START,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 32,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L820-L821
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE - 1
},
# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L823-L828
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 129,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START - 1,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": 0x500000000,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L829-L834
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 128,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START -1,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": 0,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L835-L840
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START + 128,
"cu_avail": CU_BASE
},
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START - 1,
"cu_avail": CU_BASE
},
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": 0,
"cu_avail": CU_BASE
},

# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L842-L844
# this can never happen

# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L845-L847
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": 1000, # not a u8
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},

# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L848-L850
{
"heap_prefix": [0]*64 + sig + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": 4,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},

# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L851-L853
{
"heap_prefix": [0]*64 + sig_invalid + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},

# https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L858
{
"heap_prefix": [0]*64 + sig_err + hash,
"hash_vaddr": HEAP_START + 128,
"recovery_id_val": recid,
"signature_vaddr": HEAP_START + 64,
"result_vaddr": HEAP_START,
"cu_avail": CU_BASE
},
]

test_vectors = _into_key_data("w", test_vectors_workflow)

if __name__ == "__main__":
print("Generating syscall secp256k1 tests...")

for (key, test) in test_vectors:
heap_prefix = test.get("heap_prefix", [])
syscall_ctx = pbvm.SyscallContext()
syscall_ctx.syscall_invocation.function_name = b"sol_secp256k1_recover"
syscall_ctx.syscall_invocation.heap_prefix = bytes(heap_prefix)
syscall_ctx.vm_ctx.heap_max = len(heap_prefix)
syscall_ctx.vm_ctx.r1 = test.get("hash_vaddr", 0)
syscall_ctx.vm_ctx.r2 = test.get("recovery_id_val", 0)
syscall_ctx.vm_ctx.r3 = test.get("signature_vaddr", 0)
syscall_ctx.vm_ctx.r4 = test.get("result_vaddr", 0)
syscall_ctx.instr_ctx.cu_avail = test.get("cu_avail", 0)
syscall_ctx.instr_ctx.program_id = bytes([0]*32) # solfuzz-agave expectes a program_id
syscall_ctx.vm_ctx.rodata = b"x" # fd expects some bytes

syscall_ctx.instr_ctx.epoch_context.features.features.extend([
0x4ab8b2b10003ad50, # secp256k1_recover_syscall_enabled
])

filename = str(key) + "_" + hashlib.sha3_256(syscall_ctx.instr_ctx.data).hexdigest()[:16]

serialized_instr = syscall_ctx.SerializeToString(deterministic=True)
with open(f"{OUTPUT_DIR}/{filename}.bin", "wb") as f:
f.write(serialized_instr)

print("done!")
1 change: 0 additions & 1 deletion impl/agave-v1.17
Submodule agave-v1.17 deleted from afe4b0
1 change: 0 additions & 1 deletion impl/agave-v2.0
Submodule agave-v2.0 deleted from a7ae26
1 change: 1 addition & 0 deletions impl/agave-v2.0
1 change: 0 additions & 1 deletion impl/firedancer
Submodule firedancer deleted from 8e7a55
4 changes: 2 additions & 2 deletions install.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
git submodule init && git submodule update
# git submodule init && git submodule update
sudo dnf install -y gcc-toolset-12 || true
source /opt/rh/gcc-toolset-12/enable
python3.11 -m venv test_suite_env
source test_suite_env/bin/activate
sudo dnf install -y python3.11-devel || true
make -j -C impl
# make -j -C impl
pip install .

0 comments on commit 7224872

Please sign in to comment.