Skip to main content

ethrex_rlp/
encode.rs

1use alloc::string::String;
2use alloc::vec::Vec;
3use bytes::{BufMut, Bytes};
4use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
5use ethereum_types::U256;
6
7use super::constants::RLP_NULL;
8
9/// Function for encoding a value to RLP.
10/// For encoding the value into a buffer directly, use [`RLPEncode::encode`].
11pub fn encode<T: RLPEncode>(value: T) -> Vec<u8> {
12    let mut buf = Vec::new();
13    value.encode(&mut buf);
14    buf
15}
16
17/// Calculates the encoded length of the given integer bit width (ilog2 value) and lsb
18#[inline(always)]
19const fn impl_length_integers(bits: u32, lsb: u8) -> usize {
20    // bits is the ilog2 0 based result, +8 accounts for the first byte boundary
21    let sig_len = (bits + 8) >> 3;
22    let is_multibyte_mask = ((sig_len > 1) as usize) | ((lsb > 0x7f) as usize);
23    1 + sig_len as usize * is_multibyte_mask
24}
25
26/// Computes the length needed for a given payload length
27#[inline]
28pub const fn list_length(payload_len: usize) -> usize {
29    if payload_len < 56 {
30        // short prefix
31        1 + payload_len
32    } else {
33        // encode payload_len as big endian without leading zeros
34        let be_len = payload_len.ilog2() / 8 + 1;
35        // prefix + payload_len encoding size + payload bytes
36        1 + be_len as usize + payload_len
37    }
38}
39
40/// Computes the length needed for a given byte-string and first byte
41#[inline]
42pub const fn bytes_length(bytes_len: usize, first_byte: u8) -> usize {
43    if bytes_len == 1 && first_byte <= 0x7f {
44        return 1;
45    }
46
47    if bytes_len < 56 {
48        return 1 + bytes_len; // prefix (0x80 + len) + payload
49    }
50
51    // long (>=56 bytes)
52    let be_len = bytes_len.ilog2() / 8 + 1;
53    1 + be_len as usize + bytes_len // prefix + len(len) + payload
54}
55
56/// Struct implementing `BufMut`, but only counting the number of bytes pushed into the buffer.
57#[derive(Debug, Clone, Copy, Default)]
58struct ByteCounter {
59    count: usize,
60}
61
62unsafe impl BufMut for ByteCounter {
63    fn remaining_mut(&self) -> usize {
64        usize::MAX - self.count
65    }
66
67    unsafe fn advance_mut(&mut self, cnt: usize) {
68        self.count += cnt;
69    }
70
71    fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
72        unreachable!(
73            "shouldn't be reachable since all the functions that call this are reimplemented"
74        )
75    }
76
77    fn put<T: bytes::buf::Buf>(&mut self, src: T)
78    where
79        Self: Sized,
80    {
81        self.count += src.remaining();
82    }
83
84    fn put_bytes(&mut self, _val: u8, cnt: usize) {
85        self.count += cnt;
86    }
87
88    fn put_slice(&mut self, src: &[u8]) {
89        self.count += src.len()
90    }
91}
92
93pub trait RLPEncode {
94    fn encode(&self, buf: &mut dyn BufMut);
95
96    fn length(&self) -> usize {
97        // Run the `encode` function, but only counting the bytes pushed.
98        let mut counter = ByteCounter::default();
99        self.encode(&mut counter);
100        counter.count
101    }
102
103    fn encode_to_vec(&self) -> Vec<u8> {
104        let mut buf = Vec::new();
105        self.encode(&mut buf);
106        buf
107    }
108}
109
110impl RLPEncode for bool {
111    #[inline(always)]
112    fn encode(&self, buf: &mut dyn BufMut) {
113        if *self {
114            buf.put_u8(0x01);
115        } else {
116            buf.put_u8(RLP_NULL);
117        }
118    }
119
120    #[inline(always)]
121    fn length(&self) -> usize {
122        1
123    }
124}
125
126// integer types impls
127
128#[inline]
129fn impl_encode<const N: usize>(value_be: [u8; N], buf: &mut dyn BufMut) {
130    // count leading zeros
131    let mut i = 0;
132    while i < N && value_be[i] == 0 {
133        i += 1;
134    }
135
136    // 0, also known as null or the empty string is 0x80
137    if i == N {
138        buf.put_u8(RLP_NULL);
139        return;
140    }
141
142    let first = value_be[i];
143
144    // for a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding.
145    if i == N - 1 && first <= 0x7f {
146        buf.put_u8(first);
147        return;
148    }
149
150    // if a string is 0-55 bytes long, the RLP encoding consists of a
151    // single byte with value RLP_NULL (0x80) plus the length of the string followed by the string.
152    let len = N - i;
153    buf.put_u8(RLP_NULL + len as u8);
154    buf.put_slice(&value_be[i..]);
155}
156
157impl RLPEncode for u8 {
158    fn encode(&self, buf: &mut dyn BufMut) {
159        impl_encode(self.to_be_bytes(), buf);
160    }
161
162    #[inline]
163    fn length(&self) -> usize {
164        impl_length_integers(self.checked_ilog2().unwrap_or(0), *self)
165    }
166}
167
168impl RLPEncode for u16 {
169    fn encode(&self, buf: &mut dyn BufMut) {
170        impl_encode(self.to_be_bytes(), buf);
171    }
172    #[inline]
173    fn length(&self) -> usize {
174        impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8)
175    }
176}
177
178impl RLPEncode for u32 {
179    fn encode(&self, buf: &mut dyn BufMut) {
180        impl_encode(self.to_be_bytes(), buf);
181    }
182
183    #[inline]
184    fn length(&self) -> usize {
185        impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8)
186    }
187}
188
189impl RLPEncode for u64 {
190    fn encode(&self, buf: &mut dyn BufMut) {
191        impl_encode(self.to_be_bytes(), buf);
192    }
193
194    #[inline]
195    fn length(&self) -> usize {
196        impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8)
197    }
198}
199
200impl RLPEncode for usize {
201    fn encode(&self, buf: &mut dyn BufMut) {
202        impl_encode(self.to_be_bytes(), buf);
203    }
204
205    #[inline]
206    fn length(&self) -> usize {
207        impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8)
208    }
209}
210
211impl RLPEncode for u128 {
212    fn encode(&self, buf: &mut dyn BufMut) {
213        impl_encode(self.to_be_bytes(), buf);
214    }
215
216    #[inline]
217    fn length(&self) -> usize {
218        impl_length_integers(self.checked_ilog2().unwrap_or(0), (self & 0xff) as u8)
219    }
220}
221
222impl RLPEncode for () {
223    fn encode(&self, buf: &mut dyn BufMut) {
224        buf.put_u8(RLP_NULL);
225    }
226    #[inline]
227    fn length(&self) -> usize {
228        1
229    }
230}
231
232impl RLPEncode for [u8] {
233    #[inline(always)]
234    fn encode(&self, buf: &mut dyn BufMut) {
235        if self.len() == 1 && self[0] < RLP_NULL {
236            buf.put_u8(self[0]);
237        } else {
238            let len = self.len();
239            if len < 56 {
240                buf.put_u8(RLP_NULL + len as u8);
241            } else {
242                let bytes = len.to_be_bytes();
243                let start = bytes.iter().position(|&x| x != 0).unwrap();
244                let len = bytes.len() - start;
245                buf.put_u8(0xb7 + len as u8);
246                buf.put_slice(&bytes[start..]);
247            }
248            buf.put_slice(self);
249        }
250    }
251
252    #[inline]
253    fn length(&self) -> usize {
254        if self.is_empty() {
255            return 1;
256        }
257        bytes_length(self.len(), self[0])
258    }
259}
260
261impl<const N: usize> RLPEncode for [u8; N] {
262    #[inline]
263    fn encode(&self, buf: &mut dyn BufMut) {
264        self.as_ref().encode(buf)
265    }
266
267    #[inline]
268    fn length(&self) -> usize {
269        if N == 1 && self[0] <= 0x7f {
270            return 1;
271        }
272
273        if N < 56 {
274            return 1 + N;
275        }
276
277        // long case
278        let be_len = if N == 0 {
279            1
280        } else {
281            (N.ilog2() as usize / 8) + 1
282        };
283
284        1 + be_len + N
285    }
286}
287
288impl RLPEncode for str {
289    #[inline]
290    fn encode(&self, buf: &mut dyn BufMut) {
291        self.as_bytes().encode(buf)
292    }
293
294    #[inline]
295    fn length(&self) -> usize {
296        RLPEncode::length(self.as_bytes())
297    }
298}
299
300impl RLPEncode for &str {
301    #[inline]
302    fn encode(&self, buf: &mut dyn BufMut) {
303        self.as_bytes().encode(buf)
304    }
305
306    #[inline]
307    fn length(&self) -> usize {
308        RLPEncode::length(self.as_bytes())
309    }
310}
311
312impl RLPEncode for String {
313    #[inline]
314    fn encode(&self, buf: &mut dyn BufMut) {
315        self.as_bytes().encode(buf)
316    }
317
318    #[inline]
319    fn length(&self) -> usize {
320        RLPEncode::length(self.as_bytes())
321    }
322}
323
324impl RLPEncode for U256 {
325    fn encode(&self, buf: &mut dyn BufMut) {
326        let leading_zeros_in_bytes: usize = (self.leading_zeros() / 8) as usize;
327        let bytes = self.to_big_endian();
328        bytes[leading_zeros_in_bytes..].encode(buf)
329    }
330
331    fn length(&self) -> usize {
332        let ilog = self.bits().saturating_sub(1);
333        impl_length_integers(ilog as u32, (self.low_u32() & 0xff) as u8)
334    }
335}
336
337impl<T: RLPEncode> RLPEncode for Vec<T> {
338    #[inline(always)]
339    fn encode(&self, buf: &mut dyn BufMut) {
340        if self.is_empty() {
341            buf.put_u8(0xc0);
342        } else {
343            let payload_len: usize = self.iter().map(|item| item.length()).sum();
344
345            encode_length(payload_len, buf);
346
347            for item in self {
348                item.encode(buf);
349            }
350        }
351    }
352
353    #[inline]
354    fn length(&self) -> usize {
355        if self.is_empty() {
356            // 0xc0 (1 byte)
357            return 1;
358        }
359
360        let mut payload_len = 0usize;
361        for item in self {
362            payload_len += item.length();
363        }
364
365        list_length(payload_len)
366    }
367}
368
369#[inline]
370pub fn encode_length(total_len: usize, buf: &mut dyn BufMut) {
371    if total_len < 56 {
372        buf.put_u8(0xc0 + total_len as u8);
373    } else {
374        let bytes = total_len.to_be_bytes();
375        let start = bytes.iter().position(|&x| x != 0).unwrap();
376        let len = bytes.len() - start;
377        buf.put_u8(0xf7 + len as u8);
378        buf.put_slice(&bytes[start..]);
379    }
380}
381
382impl<S: RLPEncode, T: RLPEncode> RLPEncode for (S, T) {
383    fn encode(&self, buf: &mut dyn BufMut) {
384        super::structs::Encoder::new(buf)
385            .encode_field(&self.0)
386            .encode_field(&self.1)
387            .finish();
388    }
389
390    #[inline]
391    fn length(&self) -> usize {
392        let payload_len = self.0.length() + self.1.length();
393        list_length(payload_len)
394    }
395}
396
397impl<S: RLPEncode, T: RLPEncode, U: RLPEncode> RLPEncode for (S, T, U) {
398    fn encode(&self, buf: &mut dyn BufMut) {
399        super::structs::Encoder::new(buf)
400            .encode_field(&self.0)
401            .encode_field(&self.1)
402            .encode_field(&self.2)
403            .finish();
404    }
405
406    #[inline]
407    fn length(&self) -> usize {
408        let payload_len = self.0.length() + self.1.length() + self.2.length();
409        list_length(payload_len)
410    }
411}
412
413impl<S: RLPEncode, T: RLPEncode, U: RLPEncode, V: RLPEncode> RLPEncode for (S, T, U, V) {
414    fn encode(&self, buf: &mut dyn BufMut) {
415        super::structs::Encoder::new(buf)
416            .encode_field(&self.0)
417            .encode_field(&self.1)
418            .encode_field(&self.2)
419            .encode_field(&self.3)
420            .finish();
421    }
422
423    #[inline]
424    fn length(&self) -> usize {
425        let payload_len = self.0.length() + self.1.length() + self.2.length() + self.3.length();
426        list_length(payload_len)
427    }
428}
429
430impl<S: RLPEncode, T: RLPEncode, U: RLPEncode, V: RLPEncode, W: RLPEncode> RLPEncode
431    for (S, T, U, V, W)
432{
433    fn encode(&self, buf: &mut dyn BufMut) {
434        super::structs::Encoder::new(buf)
435            .encode_field(&self.0)
436            .encode_field(&self.1)
437            .encode_field(&self.2)
438            .encode_field(&self.3)
439            .encode_field(&self.4)
440            .finish();
441    }
442
443    #[inline]
444    fn length(&self) -> usize {
445        let payload_len =
446            self.0.length() + self.1.length() + self.2.length() + self.3.length() + self.4.length();
447        list_length(payload_len)
448    }
449}
450
451impl RLPEncode for Ipv4Addr {
452    fn encode(&self, buf: &mut dyn BufMut) {
453        self.octets().encode(buf)
454    }
455
456    #[inline]
457    fn length(&self) -> usize {
458        RLPEncode::length(&self.octets())
459    }
460}
461
462impl RLPEncode for Ipv6Addr {
463    fn encode(&self, buf: &mut dyn BufMut) {
464        self.octets().encode(buf)
465    }
466
467    #[inline]
468    fn length(&self) -> usize {
469        RLPEncode::length(&self.octets())
470    }
471}
472
473impl RLPEncode for IpAddr {
474    fn encode(&self, buf: &mut dyn BufMut) {
475        match self {
476            IpAddr::V4(ip) => ip.encode(buf),
477            IpAddr::V6(ip) => ip.encode(buf),
478        }
479    }
480
481    #[inline]
482    fn length(&self) -> usize {
483        match self {
484            IpAddr::V4(ipv4_addr) => RLPEncode::length(&ipv4_addr.octets()),
485            IpAddr::V6(ipv6_addr) => RLPEncode::length(&ipv6_addr.octets()),
486        }
487    }
488}
489
490impl RLPEncode for Bytes {
491    fn encode(&self, buf: &mut dyn BufMut) {
492        self.as_ref().encode(buf)
493    }
494
495    fn length(&self) -> usize {
496        self.as_ref().length()
497    }
498}
499
500// encoding for Ethereum types
501
502impl RLPEncode for ethereum_types::H32 {
503    fn encode(&self, buf: &mut dyn BufMut) {
504        self.as_bytes().encode(buf)
505    }
506
507    #[inline]
508    fn length(&self) -> usize {
509        RLPEncode::length(self.as_bytes())
510    }
511}
512
513impl RLPEncode for ethereum_types::H64 {
514    fn encode(&self, buf: &mut dyn BufMut) {
515        self.as_bytes().encode(buf)
516    }
517
518    #[inline]
519    fn length(&self) -> usize {
520        RLPEncode::length(self.as_bytes())
521    }
522}
523
524impl RLPEncode for ethereum_types::H128 {
525    fn encode(&self, buf: &mut dyn BufMut) {
526        self.as_bytes().encode(buf)
527    }
528
529    #[inline]
530    fn length(&self) -> usize {
531        RLPEncode::length(self.as_bytes())
532    }
533}
534
535impl RLPEncode for ethereum_types::Address {
536    fn encode(&self, buf: &mut dyn BufMut) {
537        self.as_bytes().encode(buf)
538    }
539
540    #[inline]
541    fn length(&self) -> usize {
542        RLPEncode::length(self.as_bytes())
543    }
544}
545
546impl RLPEncode for ethereum_types::H256 {
547    fn encode(&self, buf: &mut dyn BufMut) {
548        self.as_bytes().encode(buf)
549    }
550
551    #[inline]
552    fn length(&self) -> usize {
553        RLPEncode::length(self.as_bytes())
554    }
555}
556
557impl RLPEncode for ethereum_types::H264 {
558    fn encode(&self, buf: &mut dyn BufMut) {
559        self.as_bytes().encode(buf)
560    }
561
562    #[inline]
563    fn length(&self) -> usize {
564        RLPEncode::length(self.as_bytes())
565    }
566}
567
568impl RLPEncode for ethereum_types::H512 {
569    fn encode(&self, buf: &mut dyn BufMut) {
570        self.as_bytes().encode(buf)
571    }
572
573    #[inline]
574    fn length(&self) -> usize {
575        RLPEncode::length(self.as_bytes())
576    }
577}
578
579impl RLPEncode for ethereum_types::Signature {
580    fn encode(&self, buf: &mut dyn BufMut) {
581        self.as_bytes().encode(buf)
582    }
583
584    #[inline]
585    fn length(&self) -> usize {
586        RLPEncode::length(self.as_bytes())
587    }
588}
589
590impl RLPEncode for ethereum_types::Bloom {
591    fn encode(&self, buf: &mut dyn BufMut) {
592        self.0.encode(buf)
593    }
594
595    #[inline]
596    fn length(&self) -> usize {
597        RLPEncode::length(&self.0)
598    }
599}
600
601pub trait PayloadRLPEncode {
602    fn encode_payload(&self, buf: &mut dyn bytes::BufMut);
603    fn encode_payload_to_vec(&self) -> Vec<u8> {
604        let mut buf = Vec::new();
605        self.encode_payload(&mut buf);
606        buf
607    }
608}