xrpl_rs/wallet/
mod.rs

1use std::convert::TryInto;
2
3use hex_literal::hex;
4use rust_decimal::Decimal;
5use secp256k1::{
6    rand::rngs::OsRng, All, Error as Secp256k1Error, KeyPair as Secp256k1KeyPair, Message,
7    PublicKey as Secp256k1PublicKey, Secp256k1, SecretKey as Secp256k1SecretKey,
8};
9use serde::Serialize;
10use serde_json::json;
11use serde_xrpl::types::Hash256;
12
13use crate::transaction::types::{PaymentChannelClaim, Transaction};
14use crate::types::account::AccountInfoRequest;
15use crate::types::fee::FeeRequest;
16use crate::types::ledger::LedgerRequest;
17use crate::types::{BigInt, CurrencyAmount};
18use crate::{Error as XRPLError, Transport, XRPL};
19use lazy_static::lazy_static;
20use ripemd::{Digest, Ripemd160};
21use sha2::{Sha256, Sha512};
22
23lazy_static! {
24    static ref DEFAULT_MAX_FEE: BigInt = BigInt(100);
25    static ref DEFAULT_LEDGER_OFFSET: u32 = 20; // Approx 1 minute.
26}
27
28static FAMILY_SEED: u8 = 0x21;
29
30#[derive(Debug)]
31pub enum Error {
32    InvalidSecret(bs58::decode::Error),
33    XRPLError(XRPLError),
34    SequenceRequired,
35    FeeRequired,
36    FeeAboveMax,
37    InvalidDrops,
38    Secp256k1Error(Secp256k1Error),
39    LastLedgerSequenceRequired,
40}
41
42impl From<XRPLError> for Error {
43    fn from(e: XRPLError) -> Self {
44        Self::XRPLError(e)
45    }
46}
47
48pub enum Signer {
49    Secp256k1(Secp256k1<All>),
50}
51
52pub enum KeyPair {
53    Secp256k1(Secp256k1KeyPair),
54}
55
56pub struct Wallet {
57    keypair: KeyPair,
58    sequence: Option<u32>,
59    fee: Option<BigInt>,
60    max_fee: BigInt,
61    ledger_offset: u32,
62    secret: String,
63}
64
65impl Wallet {
66    pub fn new_random() -> Result<Self, Error> {
67        let secret = generate_random_secret()?;
68        Self::from_secret(&secret)
69    }
70    pub fn address(&self) -> String {
71        let sha = sha256(match &self.keypair {
72            KeyPair::Secp256k1(keypair) => {
73                hex::decode(&Secp256k1PublicKey::from_keypair(&keypair).to_string()).unwrap()
74            }
75        });
76        let rip = ripemd160(&sha);
77        let prefixed = [vec![0x00], rip].concat();
78        let chk = double_sha256(&prefixed)[0..4].to_vec();
79        bs58::encode([prefixed, chk].concat())
80            .with_alphabet(bs58::Alphabet::RIPPLE)
81            .into_string()
82    }
83    pub fn from_secret(secret: &str) -> Result<Self, Error> {
84        let keypair = keypair_from_secret(secret)?;
85        Ok(Self {
86            keypair,
87            sequence: None,
88            fee: None,
89            max_fee: DEFAULT_MAX_FEE.to_owned(),
90            ledger_offset: DEFAULT_LEDGER_OFFSET.to_owned(),
91            secret: secret.to_owned(),
92        })
93    }
94    pub fn set_sequence(&mut self, sequence: u32) {
95        self.sequence = Some(sequence);
96    }
97    pub fn set_fee(&mut self, drops: BigInt) {
98        self.fee = Some(drops);
99    }
100    pub fn set_max_fee(&mut self, drops: BigInt) {
101        self.max_fee = drops;
102    }
103    pub fn set_ledger_offset<T: TryInto<BigInt>>(
104        &mut self,
105        ledger_offset: u32,
106    ) -> Result<(), Error> {
107        self.ledger_offset = ledger_offset;
108        Ok(())
109    }
110    pub async fn fill_and_sign<T: Transport>(
111        &mut self,
112        tx: &mut Transaction,
113        xrpl: &XRPL<T>,
114    ) -> Result<String, Error> {
115        self.auto_fill_fields(tx, xrpl).await?;
116        self.sign(tx)
117    }
118    pub async fn auto_fill_fields<T: Transport>(
119        &mut self,
120        tx: &mut Transaction,
121        xrpl: &XRPL<T>,
122    ) -> Result<(), Error> {
123        if tx.flags.is_none() {
124            // tfFullyCanonicalSig is flags is not otherwise specified.
125            tx.flags = Some(2147483648u32);
126        }
127        // Set the address of sender.
128        tx.account = self.address();
129        // If there is no sequence specified, then fetch from the ledger.
130        if self.sequence.is_none() {
131            let mut req = AccountInfoRequest::default();
132            req.account = self.address();
133            let account_info = xrpl.account_info(req).await?;
134            self.sequence = Some(account_info.account_data.sequence);
135        }
136        // Set the sequence and increment.
137        if let Some(sequence) = &mut self.sequence {
138            tx.sequence = *sequence;
139            *sequence += 1;
140        } else {
141            return Err(Error::SequenceRequired);
142        }
143        // If there is no fee available then fetch from the ledger.
144        if self.fee.is_none() {
145            let req = FeeRequest::default();
146            let fee = xrpl.fee(req).await?;
147            if let CurrencyAmount::XRP(drops) = fee.drops.open_ledger_fee {
148                self.fee = Some(drops);
149            }
150        }
151        // TODO calculate appropriate fee, see: https://github.com/XRPLF/xrpl.js/blob/07f36e127f76b72df57e8101979f014d9d221353/packages/xrpl/src/sugar/autofill.ts#L154
152        tx.fee = self.fee.as_ref().ok_or(Error::FeeRequired)?.clone();
153        // Check that the fee does not exceed the max fee.
154        if tx.fee > self.max_fee {
155            return Err(Error::FeeAboveMax);
156        }
157        // Assign the last ledger sequence to prevent the transaction from becoming stuck.
158        let ledger_req = LedgerRequest::default();
159        let ledger = xrpl.ledger(ledger_req).await?;
160        tx.last_ledger_sequence = ledger
161            .ledger
162            .ledger_info
163            .ledger_index
164            .ok_or(Error::LastLedgerSequenceRequired)?
165            .0
166            + self.ledger_offset;
167        Ok(())
168    }
169    // Signs the provided transaction updating the corresponding transaction fields and returns
170    // the hex encoded serialized transaction.
171    pub fn sign(&self, tx: &mut Transaction) -> Result<String, Error> {
172        match &self.keypair {
173            KeyPair::Secp256k1(keypair) => {
174                let secp = Secp256k1::new();
175                tx.signing_pub_key = Secp256k1PublicKey::from_keypair(keypair).to_string();
176                let tx_blob_for_signing =
177                    serde_xrpl::ser::to_bytes_for_signing(&serde_json::to_value(&tx).unwrap())
178                        .unwrap();
179                let mut mh = Sha512::new();
180                mh.update(&tx_blob_for_signing);
181                let mhh = mh.finalize()[..32].to_vec();
182                let message = Message::from_slice(&mhh).unwrap();
183                let sig = secp.sign_ecdsa(&message, &Secp256k1SecretKey::from_keypair(keypair));
184                tx.txn_signature = Some(sig.to_string().to_uppercase());
185            }
186        }
187        let tx_blob = serde_xrpl::ser::to_bytes(&serde_json::to_value(&tx).unwrap()).unwrap();
188        let mut th = Sha512::new();
189        th.update(&[hex!("54584e00").to_vec(), tx_blob.to_vec()].concat());
190        let transaction_hash = th.finalize()[..32].to_vec();
191        tx.hash = Some(hex::encode(transaction_hash).to_uppercase());
192        Ok(hex::encode(tx_blob).to_uppercase())
193    }
194    pub fn public_key(&self) -> String {
195        match &self.keypair {
196            KeyPair::Secp256k1(keypair) => {
197                return Secp256k1PublicKey::from_keypair(keypair).to_string();
198            }
199        }
200    }
201    pub fn private_key(&self) -> String {
202        match &self.keypair {
203            KeyPair::Secp256k1(keypair) => return keypair.display_secret().to_string(),
204        }
205    }
206    pub fn sign_message<T: Serialize>(&self, message: T) -> Result<String, Error> {
207        match &self.keypair {
208            KeyPair::Secp256k1(keypair) => {
209                let secp = Secp256k1::new();
210                let message_blob_for_signing =
211                    serde_xrpl::ser::to_bytes_for_claim(&serde_json::to_value(&message).unwrap())
212                        .unwrap();
213                let mut mh = Sha512::new();
214                mh.update(&message_blob_for_signing);
215                let mhh = mh.finalize()[..32].to_vec();
216                let message = Message::from_slice(&mhh).unwrap();
217                let sig = secp.sign_ecdsa(&message, &Secp256k1SecretKey::from_keypair(keypair));
218                Ok(sig.to_string().to_uppercase())
219            }
220        }
221    }
222    pub fn sign_payment_channel_claim(
223        &self,
224        channel: String,
225        amount: BigInt,
226    ) -> Result<String, Error> {
227        match &self.keypair {
228            KeyPair::Secp256k1(keypair) => {
229                let secp = Secp256k1::new();
230                let mut mh = Sha512::new();
231                let prefix = hex!("434c4d00").to_vec();
232                let channel_bytes = Hash256(channel).to_bytes();
233                let amount_bytes = amount.0.to_be_bytes().to_vec();
234                mh.update([prefix, channel_bytes, amount_bytes].concat());
235                let mhh = mh.finalize()[..32].to_vec();
236                let message = Message::from_slice(&mhh).unwrap();
237                let sig = secp.sign_ecdsa(&message, &Secp256k1SecretKey::from_keypair(keypair));
238                Ok(sig.to_string().to_uppercase())
239            }
240        }
241    }
242}
243
244fn decode_secret(secret: &str) -> Result<Vec<u8>, Error> {
245    Ok(bs58::decode(secret.as_bytes())
246        .with_alphabet(bs58::alphabet::Alphabet::RIPPLE)
247        .with_check(None)
248        .into_vec()
249        .map_err(|e| Error::InvalidSecret(e))?[1..]
250        .to_vec())
251}
252
253fn generate_random_secret() -> Result<String, Error> {
254    let r: [u8; 16] = rand::random();
255    Ok(bs58::encode([vec![FAMILY_SEED], r.to_vec()].concat())
256        .with_alphabet(bs58::alphabet::Alphabet::RIPPLE)
257        .with_check()
258        .into_string())
259}
260
261fn keypair_from_secret(secret: &str) -> Result<KeyPair, Error> {
262    let decoded_secret = bs58::decode(secret.as_bytes())
263        .with_alphabet(bs58::alphabet::Alphabet::RIPPLE)
264        .with_check(None)
265        .into_vec()
266        .unwrap()[1..]
267        .to_vec();
268    let secp = Secp256k1::new();
269    let mut sh = Sha512::new();
270    sh.update([decoded_secret.to_vec(), 0u32.to_be_bytes().to_vec()].concat());
271    let secret = sh.finalize();
272    let root_secret_key =
273        Secp256k1SecretKey::from_slice(&secret[..32]).map_err(|e| Error::Secp256k1Error(e))?;
274    let mut intermediate_hash = Sha512::new();
275    intermediate_hash.update(
276        [
277            Secp256k1PublicKey::from_secret_key(&secp, &root_secret_key)
278                .serialize()
279                .to_vec(),
280            0u32.to_be_bytes().to_vec(),
281            0u32.to_be_bytes().to_vec(),
282        ]
283        .concat(),
284    );
285    let mut account_secret_key =
286        Secp256k1SecretKey::from_slice(&intermediate_hash.finalize()[..32])
287            .map_err(|e| Error::Secp256k1Error(e))?;
288    account_secret_key
289        .add_assign(&root_secret_key.serialize_secret())
290        .map_err(|e| Error::Secp256k1Error(e))?;
291    let account_keypair = Secp256k1KeyPair::from_secret_key(&secp, account_secret_key);
292    Ok(KeyPair::Secp256k1(account_keypair))
293}
294
295fn sha256(i: impl AsRef<[u8]>) -> Vec<u8> {
296    let mut h = Sha256::new();
297    h.update(i);
298    h.finalize().to_vec()
299}
300
301fn double_sha256(i: impl AsRef<[u8]>) -> Vec<u8> {
302    sha256(&sha256(i))
303}
304
305fn ripemd160(i: impl AsRef<[u8]>) -> Vec<u8> {
306    let mut r = Ripemd160::new();
307    r.update(&i);
308    r.finalize().to_vec()
309}