mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-12 22:19:26 +00:00
Move Protocol to monero-wallet
This commit is contained in:
@@ -4,7 +4,10 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use core::ops::Deref;
|
||||
use std_shims::collections::{HashSet, HashMap};
|
||||
use std_shims::{
|
||||
io,
|
||||
collections::{HashSet, HashMap},
|
||||
};
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||
|
||||
@@ -15,9 +18,9 @@ use curve25519_dalek::{
|
||||
};
|
||||
|
||||
use monero_serai::{
|
||||
io::write_varint,
|
||||
io::{read_byte, read_u16, write_varint},
|
||||
primitives::{Commitment, keccak256, keccak256_to_scalar},
|
||||
ringct::EncryptedAmount,
|
||||
ringct::{RctType, EncryptedAmount},
|
||||
transaction::Input,
|
||||
};
|
||||
pub use monero_serai as monero;
|
||||
@@ -58,6 +61,137 @@ pub use send::TransactionMachine;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Monero protocol version.
|
||||
///
|
||||
/// v15 is omitted as v15 was simply v14 and v16 being active at the same time, with regards to the
|
||||
/// transactions supported. Accordingly, v16 should be used during v15.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Protocol {
|
||||
v14,
|
||||
v16,
|
||||
Custom {
|
||||
ring_len: usize,
|
||||
bp_plus: bool,
|
||||
optimal_rct_type: RctType,
|
||||
view_tags: bool,
|
||||
v16_fee: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for Protocol {
|
||||
type Error = ();
|
||||
fn try_from(version: u8) -> Result<Self, ()> {
|
||||
Ok(match version {
|
||||
14 => Protocol::v14, // TODO: 13 | 14?
|
||||
15 | 16 => Protocol::v16,
|
||||
_ => Err(())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Protocol {
|
||||
/// Amount of ring members under this protocol version.
|
||||
pub fn ring_len(&self) -> usize {
|
||||
match self {
|
||||
Protocol::v14 => 11,
|
||||
Protocol::v16 => 16,
|
||||
Protocol::Custom { ring_len, .. } => *ring_len,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the specified version uses Bulletproofs or Bulletproofs+.
|
||||
///
|
||||
/// This method will likely be reworked when versions not using Bulletproofs at all are added.
|
||||
pub fn bp_plus(&self) -> bool {
|
||||
match self {
|
||||
Protocol::v14 => false,
|
||||
Protocol::v16 => true,
|
||||
Protocol::Custom { bp_plus, .. } => *bp_plus,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make this an Option when we support pre-RCT protocols
|
||||
pub fn optimal_rct_type(&self) -> RctType {
|
||||
match self {
|
||||
Protocol::v14 => RctType::Clsag,
|
||||
Protocol::v16 => RctType::BulletproofsPlus,
|
||||
Protocol::Custom { optimal_rct_type, .. } => *optimal_rct_type,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the specified version uses view tags.
|
||||
pub fn view_tags(&self) -> bool {
|
||||
match self {
|
||||
Protocol::v14 => false,
|
||||
Protocol::v16 => true,
|
||||
Protocol::Custom { view_tags, .. } => *view_tags,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the specified version uses the fee algorithm from Monero
|
||||
/// hard fork version 16 (released in v18 binaries).
|
||||
pub fn v16_fee(&self) -> bool {
|
||||
match self {
|
||||
Protocol::v14 => false,
|
||||
Protocol::v16 => true,
|
||||
Protocol::Custom { v16_fee, .. } => *v16_fee,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
match self {
|
||||
Protocol::v14 => w.write_all(&[0, 14]),
|
||||
Protocol::v16 => w.write_all(&[0, 16]),
|
||||
Protocol::Custom { ring_len, bp_plus, optimal_rct_type, view_tags, v16_fee } => {
|
||||
// Custom, version 0
|
||||
w.write_all(&[1, 0])?;
|
||||
w.write_all(&u16::try_from(*ring_len).unwrap().to_le_bytes())?;
|
||||
w.write_all(&[u8::from(*bp_plus)])?;
|
||||
w.write_all(&[optimal_rct_type.to_byte()])?;
|
||||
w.write_all(&[u8::from(*view_tags)])?;
|
||||
w.write_all(&[u8::from(*v16_fee)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read<R: io::Read>(r: &mut R) -> io::Result<Protocol> {
|
||||
Ok(match read_byte(r)? {
|
||||
// Monero protocol
|
||||
0 => match read_byte(r)? {
|
||||
14 => Protocol::v14,
|
||||
16 => Protocol::v16,
|
||||
_ => Err(io::Error::other("unrecognized monero protocol"))?,
|
||||
},
|
||||
// Custom
|
||||
1 => match read_byte(r)? {
|
||||
0 => Protocol::Custom {
|
||||
ring_len: read_u16(r)?.into(),
|
||||
bp_plus: match read_byte(r)? {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => Err(io::Error::other("invalid bool serialization"))?,
|
||||
},
|
||||
optimal_rct_type: RctType::from_byte(read_byte(r)?)
|
||||
.ok_or_else(|| io::Error::other("invalid RctType serialization"))?,
|
||||
view_tags: match read_byte(r)? {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => Err(io::Error::other("invalid bool serialization"))?,
|
||||
},
|
||||
v16_fee: match read_byte(r)? {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => Err(io::Error::other("invalid bool serialization"))?,
|
||||
},
|
||||
},
|
||||
_ => Err(io::Error::other("unrecognized custom protocol serialization"))?,
|
||||
},
|
||||
_ => Err(io::Error::other("unrecognized protocol serialization"))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> core::cmp::Ordering {
|
||||
x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse()
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ use std::sync::{Arc, RwLock};
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||
|
||||
use monero_serai::Protocol;
|
||||
use crate::{
|
||||
address::MoneroAddress, FeeRate, SpendableOutput, Change, Decoys, SignableTransaction,
|
||||
Protocol, address::MoneroAddress, FeeRate, SpendableOutput, Change, Decoys, SignableTransaction,
|
||||
TransactionError, extra::MAX_ARBITRARY_DATA_SIZE,
|
||||
};
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ pub use monero_rpc::{FeePriority, FeeRate};
|
||||
use monero_serai::{
|
||||
io::*,
|
||||
primitives::{Commitment, keccak256},
|
||||
Protocol,
|
||||
ringct::{
|
||||
generate_key_image,
|
||||
clsag::{ClsagError, ClsagContext, Clsag},
|
||||
@@ -36,6 +35,7 @@ use monero_serai::{
|
||||
transaction::{Input, Output, Timelock, TransactionPrefix, Transaction},
|
||||
};
|
||||
use crate::{
|
||||
Protocol,
|
||||
address::{Network, AddressSpec, MoneroAddress},
|
||||
ViewPair, SpendableOutput, Decoys, PaymentId, ExtraField, Extra, key_image_sort, uniqueness,
|
||||
shared_key, commitment_mask, compact_amount_encryption,
|
||||
@@ -239,7 +239,15 @@ fn calculate_weight_and_fee(
|
||||
let mut iters = 0;
|
||||
let max_iters = 5;
|
||||
while !done {
|
||||
weight = Transaction::fee_weight(protocol, decoy_weights, n_outputs, extra, fee);
|
||||
weight = Transaction::fee_weight(
|
||||
protocol.view_tags(),
|
||||
protocol.bp_plus(),
|
||||
protocol.ring_len(),
|
||||
decoy_weights,
|
||||
n_outputs,
|
||||
extra,
|
||||
fee,
|
||||
);
|
||||
|
||||
let fee_calculated_from_weight = fee_rate.calculate_fee_from_weight(weight);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use monero_simple_request_rpc::SimpleRequestRpc;
|
||||
use monero_wallet::{
|
||||
monero::{transaction::Transaction, Protocol, DEFAULT_LOCK_WINDOW},
|
||||
monero::{transaction::Transaction, DEFAULT_LOCK_WINDOW},
|
||||
rpc::{OutputResponse, Rpc},
|
||||
SpendableOutput,
|
||||
};
|
||||
|
||||
@@ -109,9 +109,6 @@ pub async fn rpc() -> SimpleRequestRpc {
|
||||
// Mine 40 blocks to ensure decoy availability
|
||||
rpc.generate_blocks(&addr, 40).await.unwrap();
|
||||
|
||||
// Make sure we recognize the protocol
|
||||
rpc.get_protocol().await.unwrap();
|
||||
|
||||
rpc
|
||||
}
|
||||
|
||||
@@ -171,6 +168,7 @@ macro_rules! test {
|
||||
};
|
||||
|
||||
use monero_wallet::{
|
||||
Protocol,
|
||||
address::{Network, AddressSpec},
|
||||
ViewPair, Scanner, Change, DecoySelection, Decoys, FeePriority,
|
||||
SignableTransaction, SignableTransactionBuilder,
|
||||
@@ -212,11 +210,11 @@ macro_rules! test {
|
||||
|
||||
let miner_tx = get_miner_tx_output(&rpc, &view).await;
|
||||
|
||||
let protocol = rpc.get_protocol().await.unwrap();
|
||||
let protocol = Protocol::try_from(rpc.get_protocol().await.unwrap()).unwrap();
|
||||
|
||||
let builder = SignableTransactionBuilder::new(
|
||||
protocol,
|
||||
rpc.get_fee_rate(protocol, FeePriority::Unimportant).await.unwrap(),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
Change::new(
|
||||
&ViewPair::new(
|
||||
&Scalar::random(&mut OsRng) * ED25519_BASEPOINT_TABLE,
|
||||
|
||||
@@ -2,10 +2,7 @@ use rand_core::OsRng;
|
||||
|
||||
use monero_simple_request_rpc::SimpleRequestRpc;
|
||||
use monero_wallet::{
|
||||
monero::{transaction::Transaction, Protocol},
|
||||
rpc::Rpc,
|
||||
extra::Extra,
|
||||
address::SubaddressIndex,
|
||||
monero::transaction::Transaction, Protocol, rpc::Rpc, extra::Extra, address::SubaddressIndex,
|
||||
ReceivedOutput, SpendableOutput, DecoySelection, Decoys, SignableTransactionBuilder,
|
||||
};
|
||||
|
||||
@@ -109,7 +106,7 @@ test!(
|
||||
|
||||
let mut builder = SignableTransactionBuilder::new(
|
||||
protocol,
|
||||
rpc.get_fee_rate(protocol, FeePriority::Unimportant).await.unwrap(),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
Change::new(&change_view, false),
|
||||
);
|
||||
add_inputs(protocol, &rpc, vec![outputs.first().unwrap().clone()], &mut builder).await;
|
||||
@@ -293,7 +290,7 @@ test!(
|
||||
|
||||
let mut builder = SignableTransactionBuilder::new(
|
||||
protocol,
|
||||
rpc.get_fee_rate(protocol, FeePriority::Unimportant).await.unwrap(),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
Change::fingerprintable(None),
|
||||
);
|
||||
add_inputs(protocol, &rpc, vec![outputs.first().unwrap().clone()], &mut builder).await;
|
||||
|
||||
@@ -92,7 +92,7 @@ async fn from_wallet_rpc_to_self(spec: AddressSpec) {
|
||||
|
||||
// TODO: Needs https://github.com/monero-project/monero/pull/9260
|
||||
// let fee_rate = daemon_rpc
|
||||
// .get_fee_rate(daemon_rpc.get_protocol().await.unwrap(), FeePriority::Unimportant)
|
||||
// .get_fee_rate(FeePriority::Unimportant)
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user