use std::convert::TryInto;
use hex_literal::hex;
use rust_decimal::Decimal;
use secp256k1::{
rand::rngs::OsRng, All, Error as Secp256k1Error, KeyPair as Secp256k1KeyPair, Message,
PublicKey as Secp256k1PublicKey, Secp256k1, SecretKey as Secp256k1SecretKey,
};
use serde::Serialize;
use serde_json::json;
use serde_xrpl::types::Hash256;
use crate::transaction::types::{PaymentChannelClaim, Transaction};
use crate::types::account::AccountInfoRequest;
use crate::types::fee::FeeRequest;
use crate::types::ledger::LedgerRequest;
use crate::types::{BigInt, CurrencyAmount};
use crate::{Error as XRPLError, Transport, XRPL};
use lazy_static::lazy_static;
use ripemd::{Digest, Ripemd160};
use sha2::{Sha256, Sha512};
lazy_static! {
static ref DEFAULT_MAX_FEE: BigInt = BigInt(100);
static ref DEFAULT_LEDGER_OFFSET: u32 = 20; }
static FAMILY_SEED: u8 = 0x21;
#[derive(Debug)]
pub enum Error {
InvalidSecret(bs58::decode::Error),
XRPLError(XRPLError),
SequenceRequired,
FeeRequired,
FeeAboveMax,
InvalidDrops,
Secp256k1Error(Secp256k1Error),
LastLedgerSequenceRequired,
}
impl From<XRPLError> for Error {
fn from(e: XRPLError) -> Self {
Self::XRPLError(e)
}
}
pub enum Signer {
Secp256k1(Secp256k1<All>),
}
pub enum KeyPair {
Secp256k1(Secp256k1KeyPair),
}
pub struct Wallet {
keypair: KeyPair,
sequence: Option<u32>,
fee: Option<BigInt>,
max_fee: BigInt,
ledger_offset: u32,
secret: String,
}
impl Wallet {
pub fn new_random() -> Result<Self, Error> {
let secret = generate_random_secret()?;
Self::from_secret(&secret)
}
pub fn address(&self) -> String {
let sha = sha256(match &self.keypair {
KeyPair::Secp256k1(keypair) => {
hex::decode(&Secp256k1PublicKey::from_keypair(&keypair).to_string()).unwrap()
}
});
let rip = ripemd160(&sha);
let prefixed = [vec![0x00], rip].concat();
let chk = double_sha256(&prefixed)[0..4].to_vec();
bs58::encode([prefixed, chk].concat())
.with_alphabet(bs58::Alphabet::RIPPLE)
.into_string()
}
pub fn from_secret(secret: &str) -> Result<Self, Error> {
let keypair = keypair_from_secret(secret)?;
Ok(Self {
keypair,
sequence: None,
fee: None,
max_fee: DEFAULT_MAX_FEE.to_owned(),
ledger_offset: DEFAULT_LEDGER_OFFSET.to_owned(),
secret: secret.to_owned(),
})
}
pub fn set_sequence(&mut self, sequence: u32) {
self.sequence = Some(sequence);
}
pub fn set_fee(&mut self, drops: BigInt) {
self.fee = Some(drops);
}
pub fn set_max_fee(&mut self, drops: BigInt) {
self.max_fee = drops;
}
pub fn set_ledger_offset<T: TryInto<BigInt>>(
&mut self,
ledger_offset: u32,
) -> Result<(), Error> {
self.ledger_offset = ledger_offset;
Ok(())
}
pub async fn fill_and_sign<T: Transport>(
&mut self,
tx: &mut Transaction,
xrpl: &XRPL<T>,
) -> Result<String, Error> {
self.auto_fill_fields(tx, xrpl).await?;
self.sign(tx)
}
pub async fn auto_fill_fields<T: Transport>(
&mut self,
tx: &mut Transaction,
xrpl: &XRPL<T>,
) -> Result<(), Error> {
if tx.flags.is_none() {
tx.flags = Some(2147483648u32);
}
tx.account = self.address();
if self.sequence.is_none() {
let mut req = AccountInfoRequest::default();
req.account = self.address();
let account_info = xrpl.account_info(req).await?;
self.sequence = Some(account_info.account_data.sequence);
}
if let Some(sequence) = &mut self.sequence {
tx.sequence = *sequence;
*sequence += 1;
} else {
return Err(Error::SequenceRequired);
}
if self.fee.is_none() {
let req = FeeRequest::default();
let fee = xrpl.fee(req).await?;
if let CurrencyAmount::XRP(drops) = fee.drops.open_ledger_fee {
self.fee = Some(drops);
}
}
tx.fee = self.fee.as_ref().ok_or(Error::FeeRequired)?.clone();
if tx.fee > self.max_fee {
return Err(Error::FeeAboveMax);
}
let ledger_req = LedgerRequest::default();
let ledger = xrpl.ledger(ledger_req).await?;
tx.last_ledger_sequence = ledger
.ledger
.ledger_info
.ledger_index
.ok_or(Error::LastLedgerSequenceRequired)?
.0
+ self.ledger_offset;
Ok(())
}
pub fn sign(&self, tx: &mut Transaction) -> Result<String, Error> {
match &self.keypair {
KeyPair::Secp256k1(keypair) => {
let secp = Secp256k1::new();
tx.signing_pub_key = Secp256k1PublicKey::from_keypair(keypair).to_string();
let tx_blob_for_signing =
serde_xrpl::ser::to_bytes_for_signing(&serde_json::to_value(&tx).unwrap())
.unwrap();
let mut mh = Sha512::new();
mh.update(&tx_blob_for_signing);
let mhh = mh.finalize()[..32].to_vec();
let message = Message::from_slice(&mhh).unwrap();
let sig = secp.sign_ecdsa(&message, &Secp256k1SecretKey::from_keypair(keypair));
tx.txn_signature = Some(sig.to_string().to_uppercase());
}
}
let tx_blob = serde_xrpl::ser::to_bytes(&serde_json::to_value(&tx).unwrap()).unwrap();
let mut th = Sha512::new();
th.update(&[hex!("54584e00").to_vec(), tx_blob.to_vec()].concat());
let transaction_hash = th.finalize()[..32].to_vec();
tx.hash = Some(hex::encode(transaction_hash).to_uppercase());
Ok(hex::encode(tx_blob).to_uppercase())
}
pub fn public_key(&self) -> String {
match &self.keypair {
KeyPair::Secp256k1(keypair) => {
return Secp256k1PublicKey::from_keypair(keypair).to_string();
}
}
}
pub fn private_key(&self) -> String {
match &self.keypair {
KeyPair::Secp256k1(keypair) => return keypair.display_secret().to_string(),
}
}
pub fn sign_message<T: Serialize>(&self, message: T) -> Result<String, Error> {
match &self.keypair {
KeyPair::Secp256k1(keypair) => {
let secp = Secp256k1::new();
let message_blob_for_signing =
serde_xrpl::ser::to_bytes_for_claim(&serde_json::to_value(&message).unwrap())
.unwrap();
let mut mh = Sha512::new();
mh.update(&message_blob_for_signing);
let mhh = mh.finalize()[..32].to_vec();
let message = Message::from_slice(&mhh).unwrap();
let sig = secp.sign_ecdsa(&message, &Secp256k1SecretKey::from_keypair(keypair));
Ok(sig.to_string().to_uppercase())
}
}
}
pub fn sign_payment_channel_claim(
&self,
channel: String,
amount: BigInt,
) -> Result<String, Error> {
match &self.keypair {
KeyPair::Secp256k1(keypair) => {
let secp = Secp256k1::new();
let mut mh = Sha512::new();
let prefix = hex!("434c4d00").to_vec();
let channel_bytes = Hash256(channel).to_bytes();
let amount_bytes = amount.0.to_be_bytes().to_vec();
mh.update([prefix, channel_bytes, amount_bytes].concat());
let mhh = mh.finalize()[..32].to_vec();
let message = Message::from_slice(&mhh).unwrap();
let sig = secp.sign_ecdsa(&message, &Secp256k1SecretKey::from_keypair(keypair));
Ok(sig.to_string().to_uppercase())
}
}
}
}
fn decode_secret(secret: &str) -> Result<Vec<u8>, Error> {
Ok(bs58::decode(secret.as_bytes())
.with_alphabet(bs58::alphabet::Alphabet::RIPPLE)
.with_check(None)
.into_vec()
.map_err(|e| Error::InvalidSecret(e))?[1..]
.to_vec())
}
fn generate_random_secret() -> Result<String, Error> {
let r: [u8; 16] = rand::random();
Ok(bs58::encode([vec![FAMILY_SEED], r.to_vec()].concat())
.with_alphabet(bs58::alphabet::Alphabet::RIPPLE)
.with_check()
.into_string())
}
fn keypair_from_secret(secret: &str) -> Result<KeyPair, Error> {
let decoded_secret = bs58::decode(secret.as_bytes())
.with_alphabet(bs58::alphabet::Alphabet::RIPPLE)
.with_check(None)
.into_vec()
.unwrap()[1..]
.to_vec();
let secp = Secp256k1::new();
let mut sh = Sha512::new();
sh.update([decoded_secret.to_vec(), 0u32.to_be_bytes().to_vec()].concat());
let secret = sh.finalize();
let root_secret_key =
Secp256k1SecretKey::from_slice(&secret[..32]).map_err(|e| Error::Secp256k1Error(e))?;
let mut intermediate_hash = Sha512::new();
intermediate_hash.update(
[
Secp256k1PublicKey::from_secret_key(&secp, &root_secret_key)
.serialize()
.to_vec(),
0u32.to_be_bytes().to_vec(),
0u32.to_be_bytes().to_vec(),
]
.concat(),
);
let mut account_secret_key =
Secp256k1SecretKey::from_slice(&intermediate_hash.finalize()[..32])
.map_err(|e| Error::Secp256k1Error(e))?;
account_secret_key
.add_assign(&root_secret_key.serialize_secret())
.map_err(|e| Error::Secp256k1Error(e))?;
let account_keypair = Secp256k1KeyPair::from_secret_key(&secp, account_secret_key);
Ok(KeyPair::Secp256k1(account_keypair))
}
fn sha256(i: impl AsRef<[u8]>) -> Vec<u8> {
let mut h = Sha256::new();
h.update(i);
h.finalize().to_vec()
}
fn double_sha256(i: impl AsRef<[u8]>) -> Vec<u8> {
sha256(&sha256(i))
}
fn ripemd160(i: impl AsRef<[u8]>) -> Vec<u8> {
let mut r = Ripemd160::new();
r.update(&i);
r.finalize().to_vec()
}