-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathntt.rs
153 lines (131 loc) · 3.93 KB
/
ntt.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#[cfg(feature = "anchor")]
use anchor_lang::prelude::*;
use std::io;
use wormhole_io::{Readable, TypePrefixedPayload, Writeable};
use crate::{chain_id::ChainId, trimmed_amount::TrimmedAmount, utils::maybe_space::MaybeSpace};
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "anchor",
derive(AnchorSerialize, AnchorDeserialize, InitSpace)
)]
pub struct NativeTokenTransfer<A: MaybeSpace> {
pub amount: TrimmedAmount,
// TODO: is this needed?
pub source_token: [u8; 32],
// TODO: shouldn't we put this in the outer message?
pub to_chain: ChainId,
pub to: [u8; 32],
pub additional_payload: A,
}
impl<A: MaybeSpace> NativeTokenTransfer<A> {
const PREFIX: [u8; 4] = [0x99, 0x4E, 0x54, 0x54];
}
impl<A: TypePrefixedPayload + MaybeSpace> TypePrefixedPayload for NativeTokenTransfer<A> {
const TYPE: Option<u8> = None;
}
impl<A: TypePrefixedPayload + MaybeSpace> Readable for NativeTokenTransfer<A> {
const SIZE: Option<usize> = None;
fn read<R>(reader: &mut R) -> io::Result<Self>
where
Self: Sized,
R: io::Read,
{
let prefix: [u8; 4] = Readable::read(reader)?;
if prefix != Self::PREFIX {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid prefix for NativeTokenTransfer",
));
}
let amount = Readable::read(reader)?;
let source_token = Readable::read(reader)?;
let to = Readable::read(reader)?;
let to_chain = Readable::read(reader)?;
if A::SIZE != Some(0) {
// if the size is explicitly zero, this is an empty payload message
// and the size field should be skipped
// TODO: ditto todo in transceiver.rs
let _additional_payload_len: u16 = Readable::read(reader)?;
}
let additional_payload = A::read_payload(reader)?;
Ok(Self {
amount,
source_token,
to,
to_chain,
additional_payload,
})
}
}
impl<A: TypePrefixedPayload + MaybeSpace> Writeable for NativeTokenTransfer<A> {
fn written_size(&self) -> usize {
Self::PREFIX.len()
+ TrimmedAmount::SIZE.unwrap()
+ self.source_token.len()
+ self.to.len()
+ ChainId::SIZE.unwrap()
+ if A::SIZE != Some(0) {
u16::SIZE.unwrap() + self.additional_payload.written_size()
} else {
0
}
}
fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: io::Write,
{
let NativeTokenTransfer {
amount,
source_token,
to,
to_chain,
additional_payload,
} = self;
Self::PREFIX.write(writer)?;
amount.write(writer)?;
source_token.write(writer)?;
to.write(writer)?;
to_chain.write(writer)?;
if A::SIZE != Some(0) {
let len: u16 = u16::try_from(additional_payload.written_size()).expect("u16 overflow");
len.write(writer)?;
// TODO: ditto todo in transceiver.rs
A::write_payload(additional_payload, writer)
} else {
Ok(())
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "anchor",
derive(AnchorSerialize, AnchorDeserialize, InitSpace)
)]
pub struct EmptyPayload {}
impl EmptyPayload {
const PREFIX: [u8; 0] = [];
}
impl TypePrefixedPayload for EmptyPayload {
const TYPE: Option<u8> = None;
}
impl Readable for EmptyPayload {
const SIZE: Option<usize> = Some(0);
fn read<R>(_reader: &mut R) -> io::Result<Self>
where
Self: Sized,
R: io::Read,
{
Ok(Self {})
}
}
impl Writeable for EmptyPayload {
fn written_size(&self) -> usize {
Self::PREFIX.len()
}
fn write<W>(&self, _writer: &mut W) -> io::Result<()>
where
W: io::Write,
{
Ok(())
}
}