dusk_core/transfer/
withdraw.rs1use alloc::vec::Vec;
10
11use bytecheck::CheckBytes;
12use dusk_bytes::Serializable;
13use rand::{CryptoRng, RngCore};
14use rkyv::{Archive, Deserialize, Serialize};
15#[cfg(feature = "serde")]
16use serde_with::{As, DisplayFromStr};
17
18use crate::BlsScalar;
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;
28
29#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
39#[archive_attr(derive(CheckBytes))]
40#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41pub struct Withdraw {
42 pub(super) contract: ContractId,
43 #[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
44 pub(super) value: u64,
45 pub(super) receiver: WithdrawReceiver,
46 token: WithdrawReplayToken,
47 signature: WithdrawSignature,
48}
49
50impl Withdraw {
51 #[must_use]
56 pub fn new<'a, R: RngCore + CryptoRng>(
57 rng: &mut R,
58 sk: impl Into<WithdrawSecretKey<'a>>,
59 contract: ContractId,
60 value: u64,
61 receiver: WithdrawReceiver,
62 token: WithdrawReplayToken,
63 ) -> Self {
64 let mut withdraw = Self {
65 contract,
66 value,
67 receiver,
68 token,
69 signature: WithdrawSignature::Moonlight(AccountSignature::default()),
70 };
71
72 let sk = sk.into();
73
74 match (&sk, &receiver) {
75 (WithdrawSecretKey::Phoenix(_), WithdrawReceiver::Moonlight(_)) => {
76 panic!("Moonlight receiver with phoenix signer");
77 }
78 (WithdrawSecretKey::Moonlight(_), WithdrawReceiver::Phoenix(_)) => {
79 panic!("Phoenix receiver with moonlight signer");
80 }
81 _ => {}
82 }
83
84 let msg = withdraw.signature_message();
85
86 match sk {
87 WithdrawSecretKey::Phoenix(sk) => {
88 let digest = BlsScalar::hash_to_scalar(&msg);
89 let signature = sk.sign(rng, digest);
90 withdraw.signature = signature.into();
91 }
92 WithdrawSecretKey::Moonlight(sk) => {
93 let signature = sk.sign(&msg);
94 withdraw.signature = signature.into();
95 }
96 }
97
98 withdraw
99 }
100
101 #[must_use]
103 pub fn contract(&self) -> &ContractId {
104 &self.contract
105 }
106
107 #[must_use]
109 pub fn value(&self) -> u64 {
110 self.value
111 }
112
113 #[must_use]
115 pub fn receiver(&self) -> &WithdrawReceiver {
116 &self.receiver
117 }
118
119 #[must_use]
121 pub fn token(&self) -> &WithdrawReplayToken {
122 &self.token
123 }
124
125 #[must_use]
127 pub fn signature(&self) -> &WithdrawSignature {
128 &self.signature
129 }
130
131 #[must_use]
133 pub fn signature_message(&self) -> Vec<u8> {
134 let mut bytes = Vec::new();
135
136 bytes.extend(self.contract.as_bytes());
137 bytes.extend(self.value.to_bytes());
138
139 match self.receiver {
140 WithdrawReceiver::Phoenix(address) => {
141 bytes.extend(address.to_bytes());
142 }
143 WithdrawReceiver::Moonlight(account) => {
144 bytes.extend(account.to_bytes());
145 }
146 }
147
148 match &self.token {
149 WithdrawReplayToken::Phoenix(nullifiers) => {
150 for n in nullifiers {
151 bytes.extend(n.to_bytes());
152 }
153 }
154 WithdrawReplayToken::Moonlight(nonce) => {
155 bytes.extend(nonce.to_bytes());
156 }
157 }
158
159 bytes
160 }
161
162 #[must_use]
167 pub fn wrapped_signature_message(&self) -> Vec<u8> {
168 let mut bytes = self.signature_message();
169 bytes.extend(self.signature.to_var_bytes());
170 bytes
171 }
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Archive, Serialize, Deserialize)]
176#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
177#[archive_attr(derive(CheckBytes))]
178pub enum WithdrawReceiver {
179 Phoenix(StealthAddress),
182 Moonlight(AccountPublicKey),
185}
186
187#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
190#[archive_attr(derive(CheckBytes))]
191#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
192pub enum WithdrawReplayToken {
193 Phoenix(Vec<BlsScalar>),
196 Moonlight(
199 #[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
200 u64,
201 ),
202}
203
204#[derive(Debug, Clone, PartialEq)]
210pub enum WithdrawSecretKey<'a> {
211 Phoenix(&'a NoteSecretKey),
213 Moonlight(&'a AccountSecretKey),
215}
216
217impl<'a> From<&'a NoteSecretKey> for WithdrawSecretKey<'a> {
218 fn from(sk: &'a NoteSecretKey) -> Self {
219 Self::Phoenix(sk)
220 }
221}
222
223impl<'a> From<&'a AccountSecretKey> for WithdrawSecretKey<'a> {
224 fn from(sk: &'a AccountSecretKey) -> Self {
225 Self::Moonlight(sk)
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
231#[archive_attr(derive(CheckBytes))]
232#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
233pub enum WithdrawSignature {
234 Phoenix(NoteSignature),
238 Moonlight(AccountSignature),
241}
242
243impl WithdrawSignature {
244 fn to_var_bytes(&self) -> Vec<u8> {
245 match self {
246 WithdrawSignature::Phoenix(sig) => sig.to_bytes().to_vec(),
247 WithdrawSignature::Moonlight(sig) => sig.to_bytes().to_vec(),
248 }
249 }
250}
251
252impl From<NoteSignature> for WithdrawSignature {
253 fn from(sig: NoteSignature) -> Self {
254 Self::Phoenix(sig)
255 }
256}
257
258impl From<AccountSignature> for WithdrawSignature {
259 fn from(sig: AccountSignature) -> Self {
260 Self::Moonlight(sig)
261 }
262}