dusk_core/transfer/
withdraw.rs1#[cfg(feature = "serde")]
10use serde_with::{serde_as, DisplayFromStr};
11
12use alloc::vec::Vec;
13
14use bytecheck::CheckBytes;
15use dusk_bytes::Serializable;
16use rand::{CryptoRng, RngCore};
17use rkyv::{Archive, Deserialize, Serialize};
18
19use crate::abi::ContractId;
20use crate::signatures::bls::{
21 PublicKey as AccountPublicKey, SecretKey as AccountSecretKey,
22 Signature as AccountSignature,
23};
24use crate::signatures::schnorr::{
25 SecretKey as NoteSecretKey, Signature as NoteSignature,
26};
27use crate::transfer::phoenix::StealthAddress;
28use crate::BlsScalar;
29
30#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
40#[archive_attr(derive(CheckBytes))]
41#[cfg_attr(feature = "serde", cfg_eval, serde_as)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
43pub struct Withdraw {
44 pub(super) contract: ContractId,
45 #[cfg_attr(feature = "serde", serde_as(as = "DisplayFromStr"))]
46 pub(super) value: u64,
47 pub(super) receiver: WithdrawReceiver,
48 token: WithdrawReplayToken,
49 signature: WithdrawSignature,
50}
51
52impl Withdraw {
53 #[must_use]
58 pub fn new<'a, R: RngCore + CryptoRng>(
59 rng: &mut R,
60 sk: impl Into<WithdrawSecretKey<'a>>,
61 contract: ContractId,
62 value: u64,
63 receiver: WithdrawReceiver,
64 token: WithdrawReplayToken,
65 ) -> Self {
66 let mut withdraw = Self {
67 contract,
68 value,
69 receiver,
70 token,
71 signature: WithdrawSignature::Moonlight(AccountSignature::default()),
72 };
73
74 let sk = sk.into();
75
76 match (&sk, &receiver) {
77 (WithdrawSecretKey::Phoenix(_), WithdrawReceiver::Moonlight(_)) => {
78 panic!("Moonlight receiver with phoenix signer");
79 }
80 (WithdrawSecretKey::Moonlight(_), WithdrawReceiver::Phoenix(_)) => {
81 panic!("Phoenix receiver with moonlight signer");
82 }
83 _ => {}
84 }
85
86 let msg = withdraw.signature_message();
87
88 match sk {
89 WithdrawSecretKey::Phoenix(sk) => {
90 let digest = BlsScalar::hash_to_scalar(&msg);
91 let signature = sk.sign(rng, digest);
92 withdraw.signature = signature.into();
93 }
94 WithdrawSecretKey::Moonlight(sk) => {
95 let signature = sk.sign(&msg);
96 withdraw.signature = signature.into();
97 }
98 }
99
100 withdraw
101 }
102
103 #[must_use]
105 pub fn contract(&self) -> &ContractId {
106 &self.contract
107 }
108
109 #[must_use]
111 pub fn value(&self) -> u64 {
112 self.value
113 }
114
115 #[must_use]
117 pub fn receiver(&self) -> &WithdrawReceiver {
118 &self.receiver
119 }
120
121 #[must_use]
123 pub fn token(&self) -> &WithdrawReplayToken {
124 &self.token
125 }
126
127 #[must_use]
129 pub fn signature(&self) -> &WithdrawSignature {
130 &self.signature
131 }
132
133 #[must_use]
135 pub fn signature_message(&self) -> Vec<u8> {
136 let mut bytes = Vec::new();
137
138 bytes.extend(self.contract.as_bytes());
139 bytes.extend(self.value.to_bytes());
140
141 match self.receiver {
142 WithdrawReceiver::Phoenix(address) => {
143 bytes.extend(address.to_bytes());
144 }
145 WithdrawReceiver::Moonlight(account) => {
146 bytes.extend(account.to_bytes());
147 }
148 }
149
150 match &self.token {
151 WithdrawReplayToken::Phoenix(nullifiers) => {
152 for n in nullifiers {
153 bytes.extend(n.to_bytes());
154 }
155 }
156 WithdrawReplayToken::Moonlight(nonce) => {
157 bytes.extend(nonce.to_bytes());
158 }
159 }
160
161 bytes
162 }
163
164 #[must_use]
169 pub fn wrapped_signature_message(&self) -> Vec<u8> {
170 let mut bytes = self.signature_message();
171 bytes.extend(self.signature.to_var_bytes());
172 bytes
173 }
174}
175
176#[derive(Debug, Clone, Copy, PartialEq, Archive, Serialize, Deserialize)]
178#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
179#[archive_attr(derive(CheckBytes))]
180pub enum WithdrawReceiver {
181 Phoenix(StealthAddress),
184 Moonlight(AccountPublicKey),
187}
188
189#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
192#[archive_attr(derive(CheckBytes))]
193#[cfg_attr(feature = "serde", cfg_eval, serde_as)]
194#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
195pub enum WithdrawReplayToken {
196 Phoenix(Vec<BlsScalar>),
199 Moonlight(
202 #[cfg_attr(feature = "serde", serde_as(as = "DisplayFromStr"))] u64,
203 ),
204}
205
206#[derive(Debug, Clone, PartialEq)]
212pub enum WithdrawSecretKey<'a> {
213 Phoenix(&'a NoteSecretKey),
215 Moonlight(&'a AccountSecretKey),
217}
218
219impl<'a> From<&'a NoteSecretKey> for WithdrawSecretKey<'a> {
220 fn from(sk: &'a NoteSecretKey) -> Self {
221 Self::Phoenix(sk)
222 }
223}
224
225impl<'a> From<&'a AccountSecretKey> for WithdrawSecretKey<'a> {
226 fn from(sk: &'a AccountSecretKey) -> Self {
227 Self::Moonlight(sk)
228 }
229}
230
231#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
233#[archive_attr(derive(CheckBytes))]
234#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
235pub enum WithdrawSignature {
236 Phoenix(NoteSignature),
240 Moonlight(AccountSignature),
243}
244
245impl WithdrawSignature {
246 fn to_var_bytes(&self) -> Vec<u8> {
247 match self {
248 WithdrawSignature::Phoenix(sig) => sig.to_bytes().to_vec(),
249 WithdrawSignature::Moonlight(sig) => sig.to_bytes().to_vec(),
250 }
251 }
252}
253
254impl From<NoteSignature> for WithdrawSignature {
255 fn from(sig: NoteSignature) -> Self {
256 Self::Phoenix(sig)
257 }
258}
259
260impl From<AccountSignature> for WithdrawSignature {
261 fn from(sig: AccountSignature) -> Self {
262 Self::Moonlight(sig)
263 }
264}