mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 08:13:11 +00:00
Merge pull request #620 from mir-protocol/sha3_interpreter_ecrecover
Implement SHA3 in interpreter and use it in ecrecover
This commit is contained in:
commit
1a5134e4b9
@ -52,7 +52,7 @@ pub struct CpuColumnsView<T> {
|
||||
pub is_shl: T,
|
||||
pub is_shr: T,
|
||||
pub is_sar: T,
|
||||
pub is_sha3: T,
|
||||
pub is_keccak256: T,
|
||||
pub is_address: T,
|
||||
pub is_balance: T,
|
||||
pub is_origin: T,
|
||||
|
||||
@ -45,7 +45,7 @@ const OPCODES: [(u64, usize, usize); 107] = [
|
||||
(0x1c, 0, COL_MAP.is_shr),
|
||||
(0x1d, 0, COL_MAP.is_sar),
|
||||
(0x1e, 1, COL_MAP.is_invalid_1), // 0x1e-0x1f
|
||||
(0x20, 0, COL_MAP.is_sha3),
|
||||
(0x20, 0, COL_MAP.is_keccak256),
|
||||
(0x21, 0, COL_MAP.is_invalid_2),
|
||||
(0x22, 1, COL_MAP.is_invalid_3), // 0x22-0x23
|
||||
(0x24, 2, COL_MAP.is_invalid_4), // 0x24-0x27
|
||||
|
||||
@ -107,33 +107,53 @@ ecrecover_with_first_point:
|
||||
// stack: u2, Y, X, retdest
|
||||
|
||||
// Compute u2 * GENERATOR and chain the call to `ec_mul` with a call to `ec_add` to compute PUBKEY = (X,Y) + u2 * GENERATOR,
|
||||
// and a call to `final_hashing` to get the final result `SHA3(PUBKEY)[-20:]`.
|
||||
PUSH final_hashing
|
||||
// stack: final_hashing, u2, Y, X, retdest
|
||||
// and a call to `pubkey_to_addr` to get the final result `KECCAK256(PUBKEY)[-20:]`.
|
||||
PUSH pubkey_to_addr
|
||||
// stack: pubkey_to_addr, u2, Y, X, retdest
|
||||
SWAP3
|
||||
// stack: X, u2, Y, final_hashing, retdest
|
||||
// stack: X, u2, Y, pubkey_to_addr, retdest
|
||||
PUSH ec_add_valid_points_secp
|
||||
// stack: ec_add_valid_points_secp, X, u2, Y, final_hashing, retdest
|
||||
// stack: ec_add_valid_points_secp, X, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP1
|
||||
// stack: X, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
// stack: X, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
PUSH 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 // x-coordinate of generator
|
||||
// stack: Gx, X, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
// stack: Gx, X, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP1
|
||||
// stack: X, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
// stack: X, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
PUSH 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 // y-coordinate of generator
|
||||
// stack: Gy, X, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
// stack: Gy, X, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP1
|
||||
// stack: X, Gy, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
// stack: X, Gy, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP4
|
||||
// stack: u2, Gy, Gx, ec_add_valid_points_secp, X, Y, final_hashing, retdest
|
||||
// stack: u2, Gy, Gx, ec_add_valid_points_secp, X, Y, pubkey_to_addr, retdest
|
||||
SWAP2
|
||||
// stack: Gx, Gy, u2, ec_add_valid_points_secp, X, Y, final_hashing, retdest
|
||||
// stack: Gx, Gy, u2, ec_add_valid_points_secp, X, Y, pubkey_to_addr, retdest
|
||||
%jump(ec_mul_valid_point_secp)
|
||||
|
||||
// TODO
|
||||
final_hashing:
|
||||
// Take a public key (PKx, PKy) and return the associated address KECCAK256(PKx || PKy)[-20:].
|
||||
pubkey_to_addr:
|
||||
JUMPDEST
|
||||
PUSH 0xdeadbeef
|
||||
// stack: PKx, PKy, retdest
|
||||
PUSH 0
|
||||
// stack: 0, PKx, PKy, retdest
|
||||
MSTORE // TODO: switch to kernel memory (like `%mstore_current(@SEGMENT_KERNEL_GENERAL)`).
|
||||
// stack: PKy, retdest
|
||||
PUSH 0x20
|
||||
// stack: 0x20, PKy, retdest
|
||||
MSTORE
|
||||
// stack: retdest
|
||||
PUSH 0x40
|
||||
// stack: 0x40, retdest
|
||||
PUSH 0
|
||||
// stack: 0, 0x40, retdest
|
||||
KECCAK256
|
||||
// stack: hash, retdest
|
||||
PUSH 0xffffffffffffffffffffffffffffffffffffffff
|
||||
// stack: 2^160-1, hash, retdest
|
||||
AND
|
||||
// stack: address, retdest
|
||||
SWAP1
|
||||
// stack: retdest, address
|
||||
JUMP
|
||||
|
||||
// Check if v, r, and s are in correct form.
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use anyhow::bail;
|
||||
use ethereum_types::{U256, U512};
|
||||
use ethereum_types::{BigEndianHash, U256, U512};
|
||||
use keccak_hash::keccak;
|
||||
|
||||
/// Halt interpreter execution whenever a jump to this offset is done.
|
||||
const HALT_OFFSET: usize = 0xdeadbeef;
|
||||
@ -26,6 +27,11 @@ impl EvmMemory {
|
||||
U256::from_big_endian(&self.memory[offset..offset + 32])
|
||||
}
|
||||
|
||||
fn mload8(&mut self, offset: usize) -> u8 {
|
||||
self.expand(offset + 1);
|
||||
self.memory[offset]
|
||||
}
|
||||
|
||||
fn mstore(&mut self, offset: usize, value: U256) {
|
||||
self.expand(offset + 32);
|
||||
let value_be = {
|
||||
@ -124,7 +130,7 @@ impl<'a> Interpreter<'a> {
|
||||
0x1b => todo!(), // "SHL",
|
||||
0x1c => todo!(), // "SHR",
|
||||
0x1d => todo!(), // "SAR",
|
||||
0x20 => todo!(), // "KECCAK256",
|
||||
0x20 => self.run_keccak256(), // "KECCAK256",
|
||||
0x30 => todo!(), // "ADDRESS",
|
||||
0x31 => todo!(), // "BALANCE",
|
||||
0x32 => todo!(), // "ORIGIN",
|
||||
@ -303,6 +309,16 @@ impl<'a> Interpreter<'a> {
|
||||
self.push(!x);
|
||||
}
|
||||
|
||||
fn run_keccak256(&mut self) {
|
||||
let offset = self.pop().as_usize();
|
||||
let size = self.pop().as_usize();
|
||||
let bytes = (offset..offset + size)
|
||||
.map(|i| self.memory.mload8(i))
|
||||
.collect::<Vec<_>>();
|
||||
let hash = keccak(bytes);
|
||||
self.push(hash.into_uint());
|
||||
}
|
||||
|
||||
fn run_pop(&mut self) {
|
||||
self.pop();
|
||||
}
|
||||
|
||||
@ -1,20 +1,13 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use keccak_hash::keccak;
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::assembler::Kernel;
|
||||
use crate::cpu::kernel::interpreter::run;
|
||||
use crate::cpu::kernel::tests::u256ify;
|
||||
|
||||
fn pubkey_to_addr(x: U256, y: U256) -> Vec<u8> {
|
||||
let mut buf = [0; 64];
|
||||
x.to_big_endian(&mut buf[0..32]);
|
||||
y.to_big_endian(&mut buf[32..64]);
|
||||
let hash = keccak(buf);
|
||||
hash.0[12..].to_vec()
|
||||
}
|
||||
|
||||
fn test_valid_ecrecover(
|
||||
hash: &str,
|
||||
v: &str,
|
||||
@ -24,10 +17,9 @@ fn test_valid_ecrecover(
|
||||
kernel: &Kernel,
|
||||
) -> Result<()> {
|
||||
let ecrecover = kernel.global_labels["ecrecover"];
|
||||
let initial_stack = u256ify([s, r, v, hash])?;
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, r, v, hash])?;
|
||||
let stack = run(&kernel.code, ecrecover, initial_stack)?.stack;
|
||||
let got = pubkey_to_addr(stack[1], stack[0]);
|
||||
assert_eq!(got, hex::decode(&expected[2..]).unwrap());
|
||||
assert_eq!(stack[0], U256::from_str(expected).unwrap());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user