everscale_types/models/message/
envelope.rs1use crate::cell::*;
2use crate::error::Error;
3use crate::models::{Lazy, Message, MsgInfo, OwnedMessage};
4use crate::num::Tokens;
5use crate::util::unlikely;
6
7use super::IntMsgInfo;
8
9#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize))]
12#[cfg_attr(feature = "serde", serde(tag = "ty"))]
13pub enum IntermediateAddr {
14 Regular(IntermediateAddrRegular),
16 Simple(IntermediateAddrSimple),
18 Ext(IntermediateAddrExt),
20}
21
22impl IntermediateAddr {
23 pub const FULL_DEST_SAME_WORKCHAIN: Self = Self::Regular(IntermediateAddrRegular {
25 use_dest_bits: IntermediateAddrRegular::FULL_BITS,
26 });
27
28 pub const FULL_SRC_SAME_WORKCHAIN: Self =
30 Self::Regular(IntermediateAddrRegular { use_dest_bits: 0 });
31
32 pub const FULL_MASTERCHAIN: Self = Self::Simple(IntermediateAddrSimple {
34 workchain: -1,
35 address_prefix: 0b1 << 63,
36 });
37
38 pub fn workchain(&self) -> Option<i32> {
41 match self {
42 IntermediateAddr::Regular(_) => None,
43 IntermediateAddr::Simple(simple) => Some(simple.workchain as i32),
44 IntermediateAddr::Ext(ext) => Some(ext.workchain),
45 }
46 }
47
48 pub fn address_prefix(&self) -> Option<u64> {
51 match self {
52 IntermediateAddr::Regular(_) => None,
53 IntermediateAddr::Simple(simple) => Some(simple.address_prefix),
54 IntermediateAddr::Ext(ext) => Some(ext.address_prefix),
55 }
56 }
57}
58
59impl From<IntermediateAddrRegular> for IntermediateAddr {
60 #[inline]
61 fn from(addr: IntermediateAddrRegular) -> Self {
62 IntermediateAddr::Regular(addr)
63 }
64}
65
66impl From<IntermediateAddrSimple> for IntermediateAddr {
67 #[inline]
68 fn from(addr: IntermediateAddrSimple) -> Self {
69 IntermediateAddr::Simple(addr)
70 }
71}
72
73impl From<IntermediateAddrExt> for IntermediateAddr {
74 #[inline]
75 fn from(addr: IntermediateAddrExt) -> Self {
76 IntermediateAddr::Ext(addr)
77 }
78}
79
80impl Store for IntermediateAddr {
81 fn store_into(&self, builder: &mut CellBuilder, cx: &mut dyn CellContext) -> Result<(), Error> {
82 match self {
83 IntermediateAddr::Regular(addr) => {
84 ok!(builder.store_bit_zero()); addr.store_into(builder, cx)
86 }
87 IntermediateAddr::Simple(addr) => {
88 ok!(builder.store_small_uint(0b10, 2)); addr.store_into(builder, cx)
90 }
91 IntermediateAddr::Ext(addr) => {
92 ok!(builder.store_small_uint(0b11, 2)); addr.store_into(builder, cx)
94 }
95 }
96 }
97}
98
99impl<'a> Load<'a> for IntermediateAddr {
100 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
101 if unlikely(slice.load_bit()?) {
102 if unlikely(slice.load_bit()?) {
103 IntermediateAddrExt::load_from(slice).map(IntermediateAddr::Ext)
105 } else {
106 IntermediateAddrSimple::load_from(slice).map(IntermediateAddr::Simple)
108 }
109 } else {
110 IntermediateAddrRegular::load_from(slice).map(IntermediateAddr::Regular)
112 }
113 }
114}
115
116#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Store, Load)]
118#[cfg_attr(feature = "serde", derive(serde::Serialize))]
119#[tlb(validate_with = "Self::is_valid")]
120pub struct IntermediateAddrRegular {
121 use_dest_bits: u8,
123}
124
125impl IntermediateAddrRegular {
126 pub const FULL_BITS: u8 = 96;
128
129 pub const fn is_valid(&self) -> bool {
131 self.use_dest_bits <= Self::FULL_BITS
132 }
133
134 pub fn with_dest_bits(use_dest_bits: u8) -> Option<Self> {
136 (use_dest_bits <= Self::FULL_BITS).then_some(IntermediateAddrRegular { use_dest_bits })
137 }
138
139 pub fn with_src_bits(use_src_bits: u8) -> Option<Self> {
141 (use_src_bits <= Self::FULL_BITS).then(|| IntermediateAddrRegular {
142 use_dest_bits: Self::FULL_BITS - use_src_bits,
143 })
144 }
145
146 pub fn use_dest_bits(&self) -> u8 {
148 self.use_dest_bits
149 }
150
151 pub fn use_src_bits(&self) -> u8 {
153 Self::FULL_BITS - self.use_dest_bits
154 }
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Load, Store)]
159#[cfg_attr(feature = "serde", derive(serde::Serialize))]
160pub struct IntermediateAddrSimple {
161 pub workchain: i8,
167
168 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_account_prefix"))]
170 pub address_prefix: u64,
171}
172
173#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Store, Load)]
175#[cfg_attr(feature = "serde", derive(serde::Serialize))]
176pub struct IntermediateAddrExt {
177 pub workchain: i32,
179
180 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_account_prefix"))]
182 pub address_prefix: u64,
183}
184
185#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
187#[cfg_attr(feature = "serde", derive(serde::Serialize))]
188#[tlb(tag = "#4")]
189pub struct MsgEnvelope {
190 pub cur_addr: IntermediateAddr,
192 pub next_addr: IntermediateAddr,
194 pub fwd_fee_remaining: Tokens,
196 #[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
198 pub message: Lazy<OwnedMessage>,
199}
200
201impl MsgEnvelope {
202 pub fn load_message_info(&self) -> Result<IntMsgInfo, Error> {
204 if let MsgInfo::Int(info) = ok!(<_>::load_from(&mut ok!(self.message.cell.as_slice()))) {
205 Ok(info)
206 } else {
207 Err(Error::InvalidData)
208 }
209 }
210
211 pub fn load_message(&self) -> Result<Message<'_>, Error> {
213 self.message.cast_ref::<Message<'_>>().load()
214 }
215
216 pub fn load_message_owned(&self) -> Result<OwnedMessage, Error> {
218 self.message.load()
219 }
220
221 pub fn message_hash(&self) -> &HashBytes {
223 self.message.cell.repr_hash()
224 }
225
226 pub fn collect_fee(&mut self, fee: Tokens) -> bool {
228 match self.fwd_fee_remaining.checked_sub(fee) {
229 Some(remaining) => {
230 self.fwd_fee_remaining = remaining;
231 true
232 }
233 None => false,
234 }
235 }
236}
237
238#[cfg(feature = "serde")]
239fn serialize_account_prefix<S>(prefix: &u64, serializer: S) -> Result<S::Ok, S::Error>
240where
241 S: serde::Serializer,
242{
243 serializer.serialize_str(&format!("{:08x}", prefix))
244}