revm_rwasm_bytecode/metadata/
bytecode.rs1use crate::{legacy::analyze_legacy, JumpTable};
6use bincode::{
7 de::read::SliceReader, decode_from_reader, enc::write::SliceWriter, encode_into_writer, error,
8};
9use bitvec::vec::BitVec;
10use primitives::{Bytes, B256};
11use std::vec::Vec;
12
13#[derive(Debug)]
14pub struct LegacyBytecode {
16 pub hash: B256,
18 pub bytecode: Bytes,
20}
21
22#[derive(Debug)]
23pub struct AnalyzedBytecode {
25 pub bytecode: Bytes,
27 pub len: u64,
29 pub jump_table: JumpTable,
31 pub hash: B256,
33}
34
35impl Default for AnalyzedBytecode {
36 fn default() -> Self {
37 Self::new(Bytes::default(), B256::ZERO)
38 }
39}
40
41impl AnalyzedBytecode {
42 pub fn new(bytecode: Bytes, hash: B256) -> Self {
44 let len = bytecode.len() as u64;
45 let (jump_table, bytecode) = analyze_legacy(bytecode);
46 Self {
47 bytecode,
48 len,
49 jump_table,
50 hash,
51 }
52 }
53
54 pub fn hint_size(&self) -> usize {
56 8 + self.bytecode.len() + 8 + 8 + self.jump_table.as_slice().len() + 32 }
63
64 pub fn serialize(&self, buffer: &mut [u8]) -> Result<(), error::EncodeError> {
66 debug_assert!(buffer.len() >= self.hint_size());
67 let mut writer = SliceWriter::new(buffer);
68 let config = bincode::config::legacy();
69 encode_into_writer(self.hash.0, &mut writer, config)?;
70 encode_into_writer(self.len, &mut writer, config)?;
71 encode_into_writer(&self.bytecode[..], &mut writer, config)?;
72 encode_into_writer(self.jump_table.as_slice(), &mut writer, config)?;
73 Ok(())
74 }
75
76 pub fn deserialize(bytes: &[u8]) -> Result<Self, error::DecodeError> {
78 let config = bincode::config::legacy();
79 let mut reader = SliceReader::new(bytes);
80 let hash: [u8; 32] = decode_from_reader(&mut reader, config)?;
81 let len: u64 = decode_from_reader(&mut reader, config)?;
82 let bytecode: Vec<u8> = decode_from_reader(&mut reader, config)?;
83 let jump_table: Vec<u8> = decode_from_reader(&mut reader, config)?;
84 if len > bytecode.len() as u64 {
85 return Err(error::DecodeError::ArrayLengthMismatch {
86 required: len as usize,
87 found: bytecode.len(),
88 });
89 }
90 Ok(Self {
91 bytecode: bytecode.into(),
92 len,
93 jump_table: JumpTable::new(BitVec::from_vec(jump_table)),
94 hash: B256::from(hash),
95 })
96 }
97
98 #[inline]
100 pub fn as_slice(&self) -> &[u8] {
101 &self.bytecode[..self.len as usize]
102 }
103
104 #[inline]
106 pub fn len(&self) -> usize {
107 self.len as usize
108 }
109
110 #[inline]
112 pub fn is_empty(&self) -> bool {
113 self.len == 0
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use primitives::hex;
121
122 #[test]
123 fn test_analyzed_bytecode_encoding() {
124 let bytecode = [
125 0x60, 0x03, 0x56, 0x5b, ];
129 let original_bytecode = AnalyzedBytecode::new(bytecode.into(), B256::ZERO);
130 let mut raw = vec![0u8; original_bytecode.hint_size()];
131 original_bytecode.serialize(&mut raw).unwrap();
132 let new_bytecode = AnalyzedBytecode::deserialize(&raw).unwrap();
133 assert_eq!(original_bytecode.bytecode, new_bytecode.bytecode);
134 assert_eq!(original_bytecode.len, new_bytecode.len);
135 assert_eq!(
136 original_bytecode.jump_table.as_slice(),
137 new_bytecode.jump_table.as_slice()
138 );
139 for (pc, _) in bytecode.iter().enumerate() {
140 assert_eq!(
141 original_bytecode.jump_table.is_valid(pc),
142 new_bytecode.jump_table.is_valid(pc)
143 );
144 }
145 }
146
147 #[test]
148 fn test_analyzed_bytecode() {
149 let bytecode = hex!("0x608060405234801561000f575f80fd5b506004361061003f575f3560e01c80633b2e97481461004357806345773e4e1461007357806348b8bcc314610091575b5f80fd5b61005d600480360381019061005891906102e5565b6100af565b60405161006a919061039a565b60405180910390f35b61007b6100dd565b604051610088919061039a565b60405180910390f35b61009961011a565b6040516100a6919061039a565b60405180910390f35b60605f8273ffffffffffffffffffffffffffffffffffffffff163190506100d58161012f565b915050919050565b60606040518060400160405280600b81526020017f48656c6c6f20576f726c64000000000000000000000000000000000000000000815250905090565b60605f4790506101298161012f565b91505090565b60605f8203610175576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050610282565b5f8290505f5b5f82146101a457808061018d906103f0565b915050600a8261019d9190610464565b915061017b565b5f8167ffffffffffffffff8111156101bf576101be610494565b5b6040519080825280601f01601f1916602001820160405280156101f15781602001600182028036833780820191505090505b5090505b5f851461027b578180610207906104c1565b925050600a8561021791906104e8565b60306102239190610518565b60f81b8183815181106102395761023861054b565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856102749190610464565b94506101f5565b8093505050505b919050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102b48261028b565b9050919050565b6102c4816102aa565b81146102ce575f80fd5b50565b5f813590506102df816102bb565b92915050565b5f602082840312156102fa576102f9610287565b5b5f610307848285016102d1565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561034757808201518184015260208101905061032c565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61036c82610310565b610376818561031a565b935061038681856020860161032a565b61038f81610352565b840191505092915050565b5f6020820190508181035f8301526103b28184610362565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f819050919050565b5f6103fa826103e7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361042c5761042b6103ba565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61046e826103e7565b9150610479836103e7565b92508261048957610488610437565b5b828204905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f6104cb826103e7565b91505f82036104dd576104dc6103ba565b5b600182039050919050565b5f6104f2826103e7565b91506104fd836103e7565b92508261050d5761050c610437565b5b828206905092915050565b5f610522826103e7565b915061052d836103e7565b9250828201905080821115610545576105446103ba565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffdfea2646970667358221220feebf5ace29c3c3146cb63bf7ca9009c2005f349075639d267cfbd817adde3e564736f6c63430008180033");
150 let original_bytecode = AnalyzedBytecode::new(bytecode.into(), B256::ZERO);
151 assert!(original_bytecode.jump_table.is_valid(0x039a));
152 let mut raw = vec![0u8; original_bytecode.hint_size()];
153 original_bytecode.serialize(&mut raw).unwrap();
154 let new_bytecode = AnalyzedBytecode::deserialize(&raw).unwrap();
155 assert!(new_bytecode.jump_table.is_valid(0x039a));
156 }
157}