mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 16:23:12 +00:00
RLP encoding functions
This commit is contained in:
parent
f52e005307
commit
539152d767
@ -6,6 +6,8 @@ global mload_packing:
|
||||
// TODO
|
||||
// stack: value
|
||||
|
||||
// Pre stack: context, segment, offset, value, len, retdest
|
||||
// Post stack: (empty)
|
||||
global mstore_unpacking:
|
||||
// stack: context, segment, offset, value, len, retdest
|
||||
// We will enumerate i in (32 - len)..32.
|
||||
|
||||
@ -1,17 +1,127 @@
|
||||
// RLP-encode a scalar, i.e. a variable-length integer.
|
||||
// Pre stack: pos, scalar, retdest
|
||||
// Post stack: (empty)
|
||||
// Post stack: pos
|
||||
global encode_rlp_scalar:
|
||||
PANIC // TODO: implement
|
||||
// stack: pos, scalar, retdest
|
||||
// If scalar > 0x7f, this is the "medium" case.
|
||||
DUP2
|
||||
%gt_const(0x7f)
|
||||
%jumpi(encode_rlp_scalar_medium)
|
||||
|
||||
// RLP-encode a fixed-length 160-bit string. Assumes string < 2^160.
|
||||
// This is the "small" case, where the value is its own encoding.
|
||||
// stack: pos, scalar, retdest
|
||||
%stack (pos, scalar) -> (pos, scalar, pos)
|
||||
// stack: pos, scalar, pos, retdest
|
||||
%mstore_current(@SEGMENT_RLP_RAW)
|
||||
// stack: pos, retdest
|
||||
%add_const(1)
|
||||
// stack: pos', retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
encode_rlp_scalar_medium:
|
||||
// This is the "medium" case, where we write 0x80 + len followed by the
|
||||
// (big-endian) scalar bytes. We first compute the minimal number of bytes
|
||||
// needed to represent this scalar, then treat it as if it was a fixed-
|
||||
// length string with that length.
|
||||
// stack: pos, scalar, retdest
|
||||
DUP2
|
||||
%num_bytes
|
||||
// stack: scalar_bytes, pos, scalar, retdest
|
||||
%jump(encode_rlp_fixed)
|
||||
|
||||
// Convenience macro to call encode_rlp_scalar and return where we left off.
|
||||
%macro encode_rlp_scalar
|
||||
%stack (pos, scalar) -> (pos, scalar, %%after)
|
||||
%jump(encode_rlp_scalar)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
// RLP-encode a fixed-length 160 bit (20 byte) string. Assumes string < 2^160.
|
||||
// Pre stack: pos, string, retdest
|
||||
// Post stack: (empty)
|
||||
// Post stack: pos
|
||||
global encode_rlp_160:
|
||||
PANIC // TODO: implement
|
||||
PUSH 20
|
||||
%jump(encode_rlp_fixed)
|
||||
|
||||
// RLP-encode a fixed-length 256-bit string.
|
||||
// Convenience macro to call encode_rlp_160 and return where we left off.
|
||||
%macro encode_rlp_160
|
||||
%stack (pos, string) -> (pos, string, %%after)
|
||||
%jump(encode_rlp_160)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
// RLP-encode a fixed-length 256 bit (32 byte) string.
|
||||
// Pre stack: pos, string, retdest
|
||||
// Post stack: (empty)
|
||||
// Post stack: pos
|
||||
global encode_rlp_256:
|
||||
PANIC // TODO: implement
|
||||
PUSH 32
|
||||
%jump(encode_rlp_fixed)
|
||||
|
||||
// Convenience macro to call encode_rlp_256 and return where we left off.
|
||||
%macro encode_rlp_256
|
||||
%stack (pos, string) -> (pos, string, %%after)
|
||||
%jump(encode_rlp_256)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
// RLP-encode a fixed-length string with the given byte length. Assumes string < 2^(8 * len).
|
||||
encode_rlp_fixed:
|
||||
// stack: len, pos, string, retdest
|
||||
DUP1
|
||||
%add_const(0x80)
|
||||
// stack: first_byte, len, pos, string, retdest
|
||||
DUP3
|
||||
// stack: pos, first_byte, len, pos, string, retdest
|
||||
%mstore_current(@SEGMENT_RLP_RAW)
|
||||
// stack: len, pos, string, retdest
|
||||
SWAP1
|
||||
%add_const(1) // increment pos
|
||||
// stack: pos, len, string, retdest
|
||||
%stack (pos, len, string) -> (@SEGMENT_RLP_RAW, pos, string, len, encode_rlp_fixed_finish, pos, len)
|
||||
GET_CONTEXT
|
||||
// stack: context, segment, pos, string, len, encode_rlp_fixed, pos, retdest
|
||||
%jump(mstore_unpacking)
|
||||
|
||||
encode_rlp_fixed_finish:
|
||||
// stack: pos, len, retdest
|
||||
ADD
|
||||
// stack: pos', retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
// Get the number of bytes required to represent the given scalar.
|
||||
// The scalar is assumed to be non-zero, as small scalars like zero should
|
||||
// have already been handled with the small-scalar encoding.
|
||||
num_bytes:
|
||||
// stack: x, retdest
|
||||
PUSH 0 // i
|
||||
// stack: i, x, retdest
|
||||
|
||||
num_bytes_loop:
|
||||
// stack: i, x, retdest
|
||||
// If x[i] != 0, break.
|
||||
DUP2 DUP2
|
||||
// stack: i, x, i, x, retdest
|
||||
BYTE
|
||||
// stack: x[i], i, x, retdest
|
||||
%jumpi(num_bytes_finish)
|
||||
// stack: i, x, retdest
|
||||
|
||||
%add_const(1)
|
||||
// stack: i', x, retdest
|
||||
%jump(num_bytes_loop)
|
||||
|
||||
num_bytes_finish:
|
||||
// stack: i, x, retdest
|
||||
PUSH 32
|
||||
SUB
|
||||
%stack (num_bytes, x, retdest) -> (retdest, num_bytes)
|
||||
JUMP
|
||||
|
||||
// Convenience macro to call num_bytes and return where we left off.
|
||||
%macro num_bytes
|
||||
%stack (x) -> (x, %%after)
|
||||
%jump(num_bytes)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
@ -146,8 +146,16 @@ impl<'a> Interpreter<'a> {
|
||||
&self.memory.context_memory[0].segments[Segment::TxnData as usize].content
|
||||
}
|
||||
|
||||
pub(crate) fn get_rlp_memory(&self) -> Vec<u8> {
|
||||
self.memory.context_memory[self.context].segments[Segment::RlpRaw as usize]
|
||||
.content
|
||||
.iter()
|
||||
.map(|x| x.as_u32() as u8)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn set_rlp_memory(&mut self, rlp: Vec<u8>) {
|
||||
self.memory.context_memory[0].segments[Segment::RlpRaw as usize].content =
|
||||
self.memory.context_memory[self.context].segments[Segment::RlpRaw as usize].content =
|
||||
rlp.into_iter().map(U256::from).collect();
|
||||
}
|
||||
|
||||
@ -386,7 +394,6 @@ impl<'a> Interpreter<'a> {
|
||||
}
|
||||
|
||||
fn run_byte(&mut self) {
|
||||
dbg!("byte");
|
||||
let i = self.pop();
|
||||
let x = self.pop();
|
||||
let result = if i > 32.into() {
|
||||
|
||||
@ -3,6 +3,84 @@ use anyhow::Result;
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::interpreter::Interpreter;
|
||||
|
||||
#[test]
|
||||
fn test_encode_rlp_scalar_small() -> Result<()> {
|
||||
let encode_rlp_scalar = KERNEL.global_labels["encode_rlp_scalar"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let scalar = 42.into();
|
||||
let pos = 2.into();
|
||||
let initial_stack = vec![retdest, scalar, pos];
|
||||
let mut interpreter = Interpreter::new_with_kernel(encode_rlp_scalar, initial_stack);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![3.into()]; // pos' = pos + rlp_len = 2 + 1
|
||||
let expected_rlp = vec![0, 0, 42];
|
||||
assert_eq!(interpreter.stack(), expected_stack);
|
||||
assert_eq!(interpreter.get_rlp_memory(), expected_rlp);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_rlp_scalar_medium() -> Result<()> {
|
||||
let encode_rlp_scalar = KERNEL.global_labels["encode_rlp_scalar"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let scalar = 0x12345.into();
|
||||
let pos = 2.into();
|
||||
let initial_stack = vec![retdest, scalar, pos];
|
||||
let mut interpreter = Interpreter::new_with_kernel(encode_rlp_scalar, initial_stack);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![6.into()]; // pos' = pos + rlp_len = 2 + 4
|
||||
let expected_rlp = vec![0, 0, 0x80 + 3, 0x01, 0x23, 0x45];
|
||||
assert_eq!(interpreter.stack(), expected_stack);
|
||||
assert_eq!(interpreter.get_rlp_memory(), expected_rlp);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_rlp_160() -> Result<()> {
|
||||
let encode_rlp_160 = KERNEL.global_labels["encode_rlp_160"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let string = 0x12345.into();
|
||||
let pos = 0.into();
|
||||
let initial_stack = vec![retdest, string, pos];
|
||||
let mut interpreter = Interpreter::new_with_kernel(encode_rlp_160, initial_stack);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![(1 + 20).into()]; // pos'
|
||||
#[rustfmt::skip]
|
||||
let expected_rlp = vec![0x80 + 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0x23, 0x45];
|
||||
assert_eq!(interpreter.stack(), expected_stack);
|
||||
assert_eq!(interpreter.get_rlp_memory(), expected_rlp);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_rlp_256() -> Result<()> {
|
||||
let encode_rlp_256 = KERNEL.global_labels["encode_rlp_256"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let string = 0x12345.into();
|
||||
let pos = 0.into();
|
||||
let initial_stack = vec![retdest, string, pos];
|
||||
let mut interpreter = Interpreter::new_with_kernel(encode_rlp_256, initial_stack);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![(1 + 32).into()]; // pos'
|
||||
#[rustfmt::skip]
|
||||
let expected_rlp = vec![0x80 + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0x23, 0x45];
|
||||
assert_eq!(interpreter.stack(), expected_stack);
|
||||
assert_eq!(interpreter.get_rlp_memory(), expected_rlp);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_rlp_string_len_short() -> Result<()> {
|
||||
let decode_rlp_string_len = KERNEL.global_labels["decode_rlp_string_len"];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user