mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 21:49:26 +00:00
Replace EcdhInfo terminology
The ECDH encrypted the amount, yet this struct contained the encrypted amount, not some ECDH. Also corrects the types on the original EcdhInfo struct.
This commit is contained in:
@@ -32,26 +32,27 @@ pub fn generate_key_image(secret: &Zeroizing<Scalar>) -> EdwardsPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum EcdhInfo {
|
pub enum EncryptedAmount {
|
||||||
Standard { mask: Scalar, amount: Scalar },
|
Original { mask: [u8; 32], amount: [u8; 32] },
|
||||||
Bulletproof { amount: [u8; 8] },
|
Compact { amount: [u8; 8] },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcdhInfo {
|
impl EncryptedAmount {
|
||||||
pub fn read<R: Read>(rct_type: u8, r: &mut R) -> io::Result<EcdhInfo> {
|
pub fn read<R: Read>(compact: bool, r: &mut R) -> io::Result<EncryptedAmount> {
|
||||||
Ok(match rct_type {
|
Ok(if !compact {
|
||||||
0 ..= 3 => EcdhInfo::Standard { mask: read_scalar(r)?, amount: read_scalar(r)? },
|
EncryptedAmount::Original { mask: read_bytes(r)?, amount: read_bytes(r)? }
|
||||||
_ => EcdhInfo::Bulletproof { amount: read_bytes(r)? },
|
} else {
|
||||||
|
EncryptedAmount::Compact { amount: read_bytes(r)? }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
EcdhInfo::Standard { mask, amount } => {
|
EncryptedAmount::Original { mask, amount } => {
|
||||||
write_scalar(mask, w)?;
|
w.write_all(mask)?;
|
||||||
write_scalar(amount, w)
|
w.write_all(amount)
|
||||||
}
|
}
|
||||||
EcdhInfo::Bulletproof { amount } => w.write_all(amount),
|
EncryptedAmount::Compact { amount } => w.write_all(amount),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +60,7 @@ impl EcdhInfo {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct RctBase {
|
pub struct RctBase {
|
||||||
pub fee: u64,
|
pub fee: u64,
|
||||||
pub ecdh_info: Vec<EcdhInfo>,
|
pub encrypted_amounts: Vec<EncryptedAmount>,
|
||||||
pub pseudo_outs: Vec<EdwardsPoint>,
|
pub pseudo_outs: Vec<EdwardsPoint>,
|
||||||
pub commitments: Vec<EdwardsPoint>,
|
pub commitments: Vec<EdwardsPoint>,
|
||||||
}
|
}
|
||||||
@@ -78,8 +79,8 @@ impl RctBase {
|
|||||||
if rct_type == 2 {
|
if rct_type == 2 {
|
||||||
write_raw_vec(write_point, &self.pseudo_outs, w)?;
|
write_raw_vec(write_point, &self.pseudo_outs, w)?;
|
||||||
}
|
}
|
||||||
for ecdh in &self.ecdh_info {
|
for encrypted_amount in &self.encrypted_amounts {
|
||||||
ecdh.write(w)?;
|
encrypted_amount.write(w)?;
|
||||||
}
|
}
|
||||||
write_raw_vec(write_point, &self.commitments, w)
|
write_raw_vec(write_point, &self.commitments, w)
|
||||||
}
|
}
|
||||||
@@ -90,13 +91,13 @@ impl RctBase {
|
|||||||
let rct_type = read_byte(r)?;
|
let rct_type = read_byte(r)?;
|
||||||
Ok((
|
Ok((
|
||||||
if rct_type == 0 {
|
if rct_type == 0 {
|
||||||
RctBase { fee: 0, ecdh_info: vec![], pseudo_outs: vec![], commitments: vec![] }
|
RctBase { fee: 0, encrypted_amounts: vec![], pseudo_outs: vec![], commitments: vec![] }
|
||||||
} else {
|
} else {
|
||||||
RctBase {
|
RctBase {
|
||||||
fee: read_varint(r)?,
|
fee: read_varint(r)?,
|
||||||
pseudo_outs: if rct_type == 2 { read_raw_vec(read_point, inputs, r)? } else { vec![] },
|
pseudo_outs: if rct_type == 2 { read_raw_vec(read_point, inputs, r)? } else { vec![] },
|
||||||
ecdh_info: (0 .. outputs)
|
encrypted_amounts: (0 .. outputs)
|
||||||
.map(|_| EcdhInfo::read(rct_type, r))
|
.map(|_| EncryptedAmount::read(rct_type >= 4, r))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
commitments: read_raw_vec(read_point, outputs, r)?,
|
commitments: read_raw_vec(read_point, outputs, r)?,
|
||||||
}
|
}
|
||||||
@@ -114,7 +115,7 @@ pub enum RctPrunable {
|
|||||||
mlsags: Vec<Mlsag>,
|
mlsags: Vec<Mlsag>,
|
||||||
simple: bool,
|
simple: bool,
|
||||||
},
|
},
|
||||||
BulletProof {
|
Bulletproofs {
|
||||||
bulletproofs: Vec<Bulletproofs>,
|
bulletproofs: Vec<Bulletproofs>,
|
||||||
mlsags: Vec<Mlsag>,
|
mlsags: Vec<Mlsag>,
|
||||||
pseudo_outs: Vec<EdwardsPoint>,
|
pseudo_outs: Vec<EdwardsPoint>,
|
||||||
@@ -139,7 +140,7 @@ impl RctPrunable {
|
|||||||
2
|
2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RctPrunable::BulletProof { v2, .. } => {
|
RctPrunable::Bulletproofs { v2, .. } => {
|
||||||
if !v2 {
|
if !v2 {
|
||||||
3
|
3
|
||||||
} else {
|
} else {
|
||||||
@@ -168,7 +169,7 @@ impl RctPrunable {
|
|||||||
write_raw_vec(BorromeanRange::write, range_sigs, w)?;
|
write_raw_vec(BorromeanRange::write, range_sigs, w)?;
|
||||||
write_raw_vec(Mlsag::write, mlsags, w)
|
write_raw_vec(Mlsag::write, mlsags, w)
|
||||||
}
|
}
|
||||||
RctPrunable::BulletProof { bulletproofs, mlsags, pseudo_outs, v2 } => {
|
RctPrunable::Bulletproofs { bulletproofs, mlsags, pseudo_outs, v2 } => {
|
||||||
if !v2 {
|
if !v2 {
|
||||||
w.write_all(&u32::try_from(bulletproofs.len()).unwrap().to_le_bytes())?;
|
w.write_all(&u32::try_from(bulletproofs.len()).unwrap().to_le_bytes())?;
|
||||||
} else {
|
} else {
|
||||||
@@ -205,7 +206,7 @@ impl RctPrunable {
|
|||||||
mlsags: decoys.iter().map(|d| Mlsag::read(*d, r)).collect::<Result<_, _>>()?,
|
mlsags: decoys.iter().map(|d| Mlsag::read(*d, r)).collect::<Result<_, _>>()?,
|
||||||
simple: rct_type == 2,
|
simple: rct_type == 2,
|
||||||
},
|
},
|
||||||
3 | 4 => RctPrunable::BulletProof {
|
3 | 4 => RctPrunable::Bulletproofs {
|
||||||
bulletproofs: read_raw_vec(
|
bulletproofs: read_raw_vec(
|
||||||
Bulletproofs::read,
|
Bulletproofs::read,
|
||||||
if rct_type == 3 {
|
if rct_type == 3 {
|
||||||
@@ -237,7 +238,7 @@ impl RctPrunable {
|
|||||||
RctPrunable::Clsag { bulletproofs, .. } => {
|
RctPrunable::Clsag { bulletproofs, .. } => {
|
||||||
bulletproofs.iter().try_for_each(|bp| bp.signature_write(w))
|
bulletproofs.iter().try_for_each(|bp| bp.signature_write(w))
|
||||||
}
|
}
|
||||||
RctPrunable::BulletProof { bulletproofs, .. } => {
|
RctPrunable::Bulletproofs { bulletproofs, .. } => {
|
||||||
bulletproofs.iter().try_for_each(|bp| bp.signature_write(w))
|
bulletproofs.iter().try_for_each(|bp| bp.signature_write(w))
|
||||||
}
|
}
|
||||||
RctPrunable::Borromean { range_sigs, .. } => range_sigs.iter().try_for_each(|rs| rs.write(w)),
|
RctPrunable::Borromean { range_sigs, .. } => range_sigs.iter().try_for_each(|rs| rs.write(w)),
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ impl Transaction {
|
|||||||
let prefix = TransactionPrefix::read(r)?;
|
let prefix = TransactionPrefix::read(r)?;
|
||||||
let mut signatures = vec![];
|
let mut signatures = vec![];
|
||||||
let mut rct_signatures = RctSignatures {
|
let mut rct_signatures = RctSignatures {
|
||||||
base: RctBase { fee: 0, ecdh_info: vec![], pseudo_outs: vec![], commitments: vec![] },
|
base: RctBase { fee: 0, encrypted_amounts: vec![], pseudo_outs: vec![], commitments: vec![] },
|
||||||
prunable: RctPrunable::Null,
|
prunable: RctPrunable::Null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ pub use send::SignableTransactionBuilder;
|
|||||||
pub(crate) use send::InternalPayment;
|
pub(crate) use send::InternalPayment;
|
||||||
#[cfg(feature = "multisig")]
|
#[cfg(feature = "multisig")]
|
||||||
pub use send::TransactionMachine;
|
pub use send::TransactionMachine;
|
||||||
use crate::ringct::EcdhInfo;
|
use crate::ringct::EncryptedAmount;
|
||||||
|
|
||||||
fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> core::cmp::Ordering {
|
fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> core::cmp::Ordering {
|
||||||
x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse()
|
x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse()
|
||||||
@@ -93,13 +93,14 @@ pub(crate) fn amount_encryption(amount: u64, key: Scalar) -> [u8; 8] {
|
|||||||
(amount ^ u64::from_le_bytes(hash(&amount_mask)[.. 8].try_into().unwrap())).to_le_bytes()
|
(amount ^ u64::from_le_bytes(hash(&amount_mask)[.. 8].try_into().unwrap())).to_le_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn amount_decryption(amount: &EcdhInfo, key: Scalar) -> u64 {
|
fn amount_decryption(amount: &EncryptedAmount, key: Scalar) -> u64 {
|
||||||
match amount {
|
match amount {
|
||||||
EcdhInfo::Standard { mask: _, amount } => {
|
EncryptedAmount::Original { mask: _, amount } => {
|
||||||
#[cfg(feature = "experimental")]
|
#[cfg(feature = "experimental")]
|
||||||
{
|
{
|
||||||
let shared_sec = hash(&hash(key.as_bytes()));
|
let shared_sec = hash(&hash(key.as_bytes()));
|
||||||
let amount_scalar = amount - Scalar::from_bytes_mod_order(shared_sec);
|
let amount_scalar =
|
||||||
|
Scalar::from_bytes_mod_order(*amount) - Scalar::from_bytes_mod_order(shared_sec);
|
||||||
// d2b from rctTypes.cpp
|
// d2b from rctTypes.cpp
|
||||||
let amount_significant_bytes = amount_scalar.to_bytes()[0 .. 8].try_into().unwrap();
|
let amount_significant_bytes = amount_scalar.to_bytes()[0 .. 8].try_into().unwrap();
|
||||||
u64::from_le_bytes(amount_significant_bytes)
|
u64::from_le_bytes(amount_significant_bytes)
|
||||||
@@ -111,7 +112,7 @@ fn amount_decryption(amount: &EcdhInfo, key: Scalar) -> u64 {
|
|||||||
todo!("decrypting a legacy monero transaction's amount")
|
todo!("decrypting a legacy monero transaction's amount")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EcdhInfo::Bulletproof { amount } => {
|
EncryptedAmount::Compact { amount } => {
|
||||||
u64::from_le_bytes(amount_encryption(u64::from_le_bytes(*amount), key))
|
u64::from_le_bytes(amount_encryption(u64::from_le_bytes(*amount), key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ impl Scanner {
|
|||||||
commitment.amount = amount;
|
commitment.amount = amount;
|
||||||
// Regular transaction
|
// Regular transaction
|
||||||
} else {
|
} else {
|
||||||
let amount = match tx.rct_signatures.base.ecdh_info.get(o) {
|
let amount = match tx.rct_signatures.base.encrypted_amounts.get(o) {
|
||||||
Some(amount) => amount_decryption(amount, shared_key),
|
Some(amount) => amount_decryption(amount, shared_key),
|
||||||
// This should never happen, yet it may be possible with miner transactions?
|
// This should never happen, yet it may be possible with miner transactions?
|
||||||
// Using get just decreases the possibility of a panic and lets us move on in that case
|
// Using get just decreases the possibility of a panic and lets us move on in that case
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ pub use builder::SignableTransactionBuilder;
|
|||||||
mod multisig;
|
mod multisig;
|
||||||
#[cfg(feature = "multisig")]
|
#[cfg(feature = "multisig")]
|
||||||
pub use multisig::TransactionMachine;
|
pub use multisig::TransactionMachine;
|
||||||
use crate::ringct::EcdhInfo;
|
use crate::ringct::EncryptedAmount;
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
||||||
@@ -630,7 +630,7 @@ impl SignableTransaction {
|
|||||||
|
|
||||||
let mut fee = self.inputs.iter().map(|input| input.commitment().amount).sum::<u64>();
|
let mut fee = self.inputs.iter().map(|input| input.commitment().amount).sum::<u64>();
|
||||||
let mut tx_outputs = Vec::with_capacity(outputs.len());
|
let mut tx_outputs = Vec::with_capacity(outputs.len());
|
||||||
let mut ecdh_info = Vec::with_capacity(outputs.len());
|
let mut encrypted_amounts = Vec::with_capacity(outputs.len());
|
||||||
for output in &outputs {
|
for output in &outputs {
|
||||||
fee -= output.commitment.amount;
|
fee -= output.commitment.amount;
|
||||||
tx_outputs.push(Output {
|
tx_outputs.push(Output {
|
||||||
@@ -638,7 +638,7 @@ impl SignableTransaction {
|
|||||||
key: output.dest.compress(),
|
key: output.dest.compress(),
|
||||||
view_tag: Some(output.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
view_tag: Some(output.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
||||||
});
|
});
|
||||||
ecdh_info.push(EcdhInfo::Bulletproof { amount: output.amount });
|
encrypted_amounts.push(EncryptedAmount::Compact { amount: output.amount });
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
@@ -654,7 +654,7 @@ impl SignableTransaction {
|
|||||||
rct_signatures: RctSignatures {
|
rct_signatures: RctSignatures {
|
||||||
base: RctBase {
|
base: RctBase {
|
||||||
fee,
|
fee,
|
||||||
ecdh_info,
|
encrypted_amounts,
|
||||||
pseudo_outs: vec![],
|
pseudo_outs: vec![],
|
||||||
commitments: commitments.iter().map(|commitment| commitment.calculate()).collect(),
|
commitments: commitments.iter().map(|commitment| commitment.calculate()).collect(),
|
||||||
},
|
},
|
||||||
@@ -758,8 +758,8 @@ impl Eventuality {
|
|||||||
view_tag: Some(expected.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
view_tag: Some(expected.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
||||||
} != actual) ||
|
} != actual) ||
|
||||||
(Some(&expected.commitment.calculate()) != tx.rct_signatures.base.commitments.get(o)) ||
|
(Some(&expected.commitment.calculate()) != tx.rct_signatures.base.commitments.get(o)) ||
|
||||||
(Some(&EcdhInfo::Bulletproof { amount: expected.amount }) !=
|
(Some(&EncryptedAmount::Compact { amount: expected.amount }) !=
|
||||||
tx.rct_signatures.base.ecdh_info.get(o))
|
tx.rct_signatures.base.encrypted_amounts.get(o))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user