mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
Move Protocol to monero-wallet
This commit is contained in:
@@ -23,7 +23,6 @@ use serde_json::{Value, json};
|
||||
|
||||
use monero_serai::{
|
||||
io::*,
|
||||
Protocol,
|
||||
transaction::{Input, Timelock, Transaction},
|
||||
block::Block,
|
||||
};
|
||||
@@ -154,9 +153,6 @@ pub enum RpcError {
|
||||
/// The node is invalid per the expected protocol.
|
||||
#[cfg_attr(feature = "std", error("invalid node ({0})"))]
|
||||
InvalidNode(String),
|
||||
/// The node is running an unsupported protocol.
|
||||
#[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))]
|
||||
UnsupportedProtocol(usize),
|
||||
/// Requested transactions weren't found.
|
||||
#[cfg_attr(feature = "std", error("transactions not found"))]
|
||||
TransactionsNotFound(Vec<[u8; 32]>),
|
||||
@@ -210,42 +206,6 @@ fn read_epee_vi<R: io::Read>(reader: &mut R) -> io::Result<u64> {
|
||||
Ok(vi)
|
||||
}
|
||||
|
||||
async fn get_fee_rate_v14(rpc: &impl Rpc, priority: FeePriority) -> Result<FeeRate, RpcError> {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct FeeResponseV14 {
|
||||
status: String,
|
||||
fee: u64,
|
||||
quantization_mask: u64,
|
||||
}
|
||||
|
||||
// https://github.com/monero-project/monero/blob/94e67bf96bbc010241f29ada6abc89f49a81759c/
|
||||
// src/wallet/wallet2.cpp#L7569-L7584
|
||||
// https://github.com/monero-project/monero/blob/94e67bf96bbc010241f29ada6abc89f49a81759c/
|
||||
// src/wallet/wallet2.cpp#L7660-L7661
|
||||
let priority_idx =
|
||||
usize::try_from(if priority.fee_priority() == 0 { 1 } else { priority.fee_priority() - 1 })
|
||||
.map_err(|_| RpcError::InvalidPriority)?;
|
||||
let multipliers = [1, 5, 25, 1000];
|
||||
if priority_idx >= multipliers.len() {
|
||||
// though not an RPC error, it seems sensible to treat as such
|
||||
Err(RpcError::InvalidPriority)?;
|
||||
}
|
||||
let fee_multiplier = multipliers[priority_idx];
|
||||
|
||||
let res: FeeResponseV14 = rpc
|
||||
.json_rpc_call(
|
||||
"get_fee_estimate",
|
||||
Some(json!({ "grace_blocks": GRACE_BLOCKS_FOR_FEE_ESTIMATE })),
|
||||
)
|
||||
.await?;
|
||||
|
||||
if res.status != "OK" {
|
||||
Err(RpcError::InvalidFee)?;
|
||||
}
|
||||
|
||||
FeeRate::new(res.fee * fee_multiplier, res.quantization_mask)
|
||||
}
|
||||
|
||||
/// An RPC connection to a Monero daemon.
|
||||
///
|
||||
/// This is abstract such that users can use an HTTP library (which being their choice), a
|
||||
@@ -305,10 +265,12 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
}
|
||||
|
||||
/// Get the active blockchain protocol version.
|
||||
async fn get_protocol(&self) -> Result<Protocol, RpcError> {
|
||||
///
|
||||
/// This is specifically the major version within the most recent block header.
|
||||
async fn get_protocol(&self) -> Result<u8, RpcError> {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct ProtocolResponse {
|
||||
major_version: usize,
|
||||
major_version: u8,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@@ -317,16 +279,11 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
}
|
||||
|
||||
Ok(
|
||||
match self
|
||||
self
|
||||
.json_rpc_call::<LastHeaderResponse>("get_last_block_header", None)
|
||||
.await?
|
||||
.block_header
|
||||
.major_version
|
||||
{
|
||||
13 | 14 => Protocol::v14,
|
||||
15 | 16 => Protocol::v16,
|
||||
protocol => Err(RpcError::UnsupportedProtocol(protocol))?,
|
||||
},
|
||||
.major_version,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -789,18 +746,12 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
///
|
||||
/// This may be manipulated to unsafe levels and MUST be sanity checked.
|
||||
// TODO: Take a sanity check argument
|
||||
async fn get_fee_rate(
|
||||
&self,
|
||||
protocol: Protocol,
|
||||
priority: FeePriority,
|
||||
) -> Result<FeeRate, RpcError> {
|
||||
// TODO: Implement wallet2's adjust_priority which by default automatically uses a lower
|
||||
// priority than provided depending on the backlog in the pool
|
||||
if protocol.v16_fee() {
|
||||
async fn get_fee_rate(&self, priority: FeePriority) -> Result<FeeRate, RpcError> {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct FeeResponse {
|
||||
status: String,
|
||||
fees: Vec<u64>,
|
||||
fees: Option<Vec<u64>>,
|
||||
fee: u64,
|
||||
quantization_mask: u64,
|
||||
}
|
||||
|
||||
@@ -811,6 +762,11 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
)
|
||||
.await?;
|
||||
|
||||
if res.status != "OK" {
|
||||
Err(RpcError::InvalidFee)?;
|
||||
}
|
||||
|
||||
if let Some(fees) = res.fees {
|
||||
// https://github.com/monero-project/monero/blob/94e67bf96bbc010241f29ada6abc89f49a81759c/
|
||||
// src/wallet/wallet2.cpp#L7615-L7620
|
||||
let priority_idx = usize::try_from(if priority.fee_priority() >= 4 {
|
||||
@@ -820,15 +776,27 @@ pub trait Rpc: Sync + Clone + Debug {
|
||||
})
|
||||
.map_err(|_| RpcError::InvalidPriority)?;
|
||||
|
||||
if res.status != "OK" {
|
||||
Err(RpcError::InvalidFee)
|
||||
} else if priority_idx >= res.fees.len() {
|
||||
if priority_idx >= fees.len() {
|
||||
Err(RpcError::InvalidPriority)
|
||||
} else {
|
||||
FeeRate::new(res.fees[priority_idx], res.quantization_mask)
|
||||
FeeRate::new(fees[priority_idx], res.quantization_mask)
|
||||
}
|
||||
} else {
|
||||
get_fee_rate_v14(self, priority).await
|
||||
// https://github.com/monero-project/monero/blob/94e67bf96bbc010241f29ada6abc89f49a81759c/
|
||||
// src/wallet/wallet2.cpp#L7569-L7584
|
||||
// https://github.com/monero-project/monero/blob/94e67bf96bbc010241f29ada6abc89f49a81759c/
|
||||
// src/wallet/wallet2.cpp#L7660-L7661
|
||||
let priority_idx =
|
||||
usize::try_from(if priority.fee_priority() == 0 { 1 } else { priority.fee_priority() - 1 })
|
||||
.map_err(|_| RpcError::InvalidPriority)?;
|
||||
let multipliers = [1, 5, 25, 1000];
|
||||
if priority_idx >= multipliers.len() {
|
||||
// though not an RPC error, it seems sensible to treat as such
|
||||
Err(RpcError::InvalidPriority)?;
|
||||
}
|
||||
let fee_multiplier = multipliers[priority_idx];
|
||||
|
||||
FeeRate::new(res.fee * fee_multiplier, res.quantization_mask)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc = include_str!("../README.md")]
|
||||
// #![deny(missing_docs)] // TODO
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use std_shims::io as stdio;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
pub use monero_io as io;
|
||||
pub use monero_generators as generators;
|
||||
pub use monero_primitives as primitives;
|
||||
|
||||
mod merkle;
|
||||
|
||||
use monero_io as serialize;
|
||||
use serialize::{read_byte, read_u16};
|
||||
|
||||
/// Ring Signature structs and functionality.
|
||||
pub mod ring_signatures;
|
||||
|
||||
/// RingCT structs and functionality.
|
||||
pub mod ringct;
|
||||
use ringct::RctType;
|
||||
|
||||
/// Transaction structs.
|
||||
pub mod transaction;
|
||||
@@ -30,123 +23,3 @@ pub mod block;
|
||||
pub const DEFAULT_LOCK_WINDOW: usize = 10;
|
||||
pub const COINBASE_LOCK_WINDOW: usize = 60;
|
||||
pub const BLOCK_TIME: usize = 120;
|
||||
|
||||
/// 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 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: stdio::Write>(&self, w: &mut W) -> stdio::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: stdio::Read>(r: &mut R) -> stdio::Result<Protocol> {
|
||||
Ok(match read_byte(r)? {
|
||||
// Monero protocol
|
||||
0 => match read_byte(r)? {
|
||||
14 => Protocol::v14,
|
||||
16 => Protocol::v16,
|
||||
_ => Err(stdio::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(stdio::Error::other("invalid bool serialization"))?,
|
||||
},
|
||||
optimal_rct_type: RctType::from_byte(read_byte(r)?)
|
||||
.ok_or_else(|| stdio::Error::other("invalid RctType serialization"))?,
|
||||
view_tags: match read_byte(r)? {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => Err(stdio::Error::other("invalid bool serialization"))?,
|
||||
},
|
||||
v16_fee: match read_byte(r)? {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => Err(stdio::Error::other("invalid bool serialization"))?,
|
||||
},
|
||||
},
|
||||
_ => Err(stdio::Error::other("unrecognized custom protocol serialization"))?,
|
||||
},
|
||||
_ => Err(stdio::Error::other("unrecognized protocol serialization"))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ use crate::{
|
||||
io::*,
|
||||
generators::hash_to_point,
|
||||
ringct::{mlsag::Mlsag, clsag::Clsag, borromean::BorromeanRange, bulletproofs::Bulletproof},
|
||||
Protocol,
|
||||
};
|
||||
|
||||
/// Generate a key image for a given key. Defined as `x * hash_to_point(xG)`.
|
||||
@@ -227,10 +226,13 @@ pub enum RctPrunable {
|
||||
}
|
||||
|
||||
impl RctPrunable {
|
||||
pub fn fee_weight(protocol: Protocol, inputs: usize, outputs: usize) -> usize {
|
||||
#[rustfmt::skip]
|
||||
pub fn fee_weight(bp_plus: bool, ring_len: usize, inputs: usize, outputs: usize) -> usize {
|
||||
// 1 byte for number of BPs (technically a VarInt, yet there's always just zero or one)
|
||||
1 + Bulletproof::fee_weight(protocol.bp_plus(), outputs) +
|
||||
(inputs * (Clsag::fee_weight(protocol.ring_len()) + 32))
|
||||
1 +
|
||||
Bulletproof::fee_weight(bp_plus, outputs) +
|
||||
// There's both the CLSAG and the pseudo-out
|
||||
(inputs * (Clsag::fee_weight(ring_len) + 32))
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, w: &mut W, rct_type: RctType) -> io::Result<()> {
|
||||
@@ -383,8 +385,14 @@ impl RctSignatures {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fee_weight(protocol: Protocol, inputs: usize, outputs: usize, fee: u64) -> usize {
|
||||
RctBase::fee_weight(outputs, fee) + RctPrunable::fee_weight(protocol, inputs, outputs)
|
||||
pub fn fee_weight(
|
||||
bp_plus: bool,
|
||||
ring_len: usize,
|
||||
inputs: usize,
|
||||
outputs: usize,
|
||||
fee: u64,
|
||||
) -> usize {
|
||||
RctBase::fee_weight(outputs, fee) + RctPrunable::fee_weight(bp_plus, ring_len, inputs, outputs)
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
|
||||
@@ -13,7 +13,6 @@ use crate::{
|
||||
primitives::keccak256,
|
||||
ring_signatures::RingSignature,
|
||||
ringct::{bulletproofs::Bulletproof, RctType, RctBase, RctPrunable, RctSignatures},
|
||||
Protocol,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
@@ -254,15 +253,19 @@ pub struct Transaction {
|
||||
}
|
||||
|
||||
impl Transaction {
|
||||
// TODO: Replace ring_len, decoy_weights for &[&[usize]], where the inner buf is the decoy
|
||||
// offsets
|
||||
pub fn fee_weight(
|
||||
protocol: Protocol,
|
||||
view_tags: bool,
|
||||
bp_plus: bool,
|
||||
ring_len: usize,
|
||||
decoy_weights: &[usize],
|
||||
outputs: usize,
|
||||
extra: usize,
|
||||
fee: u64,
|
||||
) -> usize {
|
||||
TransactionPrefix::fee_weight(decoy_weights, outputs, protocol.view_tags(), extra) +
|
||||
RctSignatures::fee_weight(protocol, decoy_weights.len(), outputs, fee)
|
||||
TransactionPrefix::fee_weight(decoy_weights, outputs, view_tags, extra) +
|
||||
RctSignatures::fee_weight(bp_plus, ring_len, decoy_weights.len(), outputs, fee)
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ use frost::{curve::Ed25519, ThresholdKeys};
|
||||
|
||||
use monero_simple_request_rpc::SimpleRequestRpc;
|
||||
use monero_wallet::{
|
||||
monero::{Protocol, ringct::RctType, transaction::Transaction, block::Block},
|
||||
monero::{ringct::RctType, transaction::Transaction, block::Block},
|
||||
Protocol,
|
||||
rpc::{RpcError, Rpc},
|
||||
ViewPair, Scanner,
|
||||
address::{Network as MoneroNetwork, SubaddressIndex, AddressSpec},
|
||||
@@ -315,25 +316,14 @@ impl Monero {
|
||||
let fee_rate = self.median_fee(&block_for_fee).await?;
|
||||
|
||||
// Get the protocol for the specified block number
|
||||
// For now, this should just be v16, the latest deployed protocol, since there's no upcoming
|
||||
// hard fork to be mindful of
|
||||
let get_protocol = || Protocol::v16;
|
||||
|
||||
#[cfg(not(test))]
|
||||
let protocol = get_protocol();
|
||||
let protocol = Protocol::try_from(block_for_fee.header.major_version)
|
||||
.map_err(|()| NetworkError::ConnectionError)?;
|
||||
// If this is a test, we won't be using a mainnet node and need a distinct protocol
|
||||
// determination
|
||||
// Just use whatever the node expects
|
||||
#[cfg(test)]
|
||||
let protocol = self.rpc.get_protocol().await.unwrap();
|
||||
|
||||
// Hedge against the above codegen failing by having an always included runtime check
|
||||
if !cfg!(test) {
|
||||
assert_eq!(protocol, get_protocol());
|
||||
}
|
||||
|
||||
// Check a fork hasn't occurred which this processor hasn't been updated for
|
||||
assert_eq!(protocol, self.rpc.get_protocol().await.map_err(map_rpc_err)?);
|
||||
let protocol = Protocol::try_from(self.rpc.get_protocol().await.unwrap()).unwrap();
|
||||
|
||||
let spendable_outputs = inputs.iter().map(|input| input.0.clone()).collect::<Vec<_>>();
|
||||
|
||||
@@ -774,7 +764,7 @@ impl Network for Monero {
|
||||
// The dust should always be sufficient for the fee
|
||||
let fee = Monero::DUST;
|
||||
|
||||
let protocol = self.rpc.get_protocol().await.unwrap();
|
||||
let protocol = Protocol::try_from(self.rpc.get_protocol().await.unwrap()).unwrap();
|
||||
|
||||
let decoys = Decoys::fingerprintable_canonical_select(
|
||||
&mut OsRng,
|
||||
@@ -795,7 +785,7 @@ impl Network for Monero {
|
||||
vec![(address.into(), amount - fee)],
|
||||
&Change::fingerprintable(Some(Self::test_address().into())),
|
||||
vec![],
|
||||
self.rpc.get_fee_rate(protocol, FeePriority::Unimportant).await.unwrap(),
|
||||
self.rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.sign(&mut OsRng, &Zeroizing::new(Scalar::ONE.0))
|
||||
|
||||
@@ -349,7 +349,8 @@ async fn mint_and_burn_test() {
|
||||
{
|
||||
use curve25519_dalek::{constants::ED25519_BASEPOINT_POINT, scalar::Scalar};
|
||||
use monero_wallet::{
|
||||
monero::{io::decompress_point, Protocol, transaction::Timelock},
|
||||
monero::{io::decompress_point, transaction::Timelock},
|
||||
Protocol,
|
||||
rpc::Rpc,
|
||||
ViewPair, Scanner, DecoySelection, Decoys, Change, FeePriority, SignableTransaction,
|
||||
address::{Network, AddressType, AddressMeta, MoneroAddress},
|
||||
@@ -397,7 +398,7 @@ async fn mint_and_burn_test() {
|
||||
)],
|
||||
&Change::new(&view_pair, false),
|
||||
vec![Shorthand::transfer(None, serai_addr).encode()],
|
||||
rpc.get_fee_rate(Protocol::v16, FeePriority::Unimportant).await.unwrap(),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.sign(&mut OsRng, &Zeroizing::new(Scalar::ONE))
|
||||
|
||||
@@ -438,7 +438,8 @@ impl Wallet {
|
||||
use monero_simple_request_rpc::SimpleRequestRpc;
|
||||
use monero_wallet::{
|
||||
rpc::Rpc,
|
||||
monero::{Protocol, io::decompress_point},
|
||||
monero::io::decompress_point,
|
||||
Protocol,
|
||||
address::{Network, AddressType, AddressMeta, Address},
|
||||
SpendableOutput, DecoySelection, Decoys, Change, FeePriority, Scanner,
|
||||
SignableTransaction,
|
||||
@@ -492,7 +493,7 @@ impl Wallet {
|
||||
vec![(to_addr, AMOUNT)],
|
||||
&Change::new(view_pair, false),
|
||||
data,
|
||||
rpc.get_fee_rate(Protocol::v16, FeePriority::Unimportant).await.unwrap(),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.sign(&mut OsRng, spend_key)
|
||||
|
||||
Reference in New Issue
Block a user