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