support add/read multiple arbitrary tx data (#189)

* support add/read multiple arbitrary tx  data

* fix clippy errors

* resolve pr issues
This commit is contained in:
akildemir
2022-12-09 18:58:11 +03:00
committed by GitHub
parent 9e82416e7d
commit d5a5704ba4
6 changed files with 128 additions and 34 deletions

View File

@@ -4,7 +4,10 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::{
Protocol,
wallet::{address::MoneroAddress, Fee, SpendableOutput, SignableTransaction, TransactionError},
wallet::{
address::MoneroAddress, Fee, SpendableOutput, SignableTransaction, TransactionError,
extra::MAX_TX_EXTRA_NONCE_SIZE,
},
};
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
@@ -15,14 +18,14 @@ struct SignableTransactionBuilderInternal {
inputs: Vec<SpendableOutput>,
payments: Vec<(MoneroAddress, u64)>,
change_address: Option<MoneroAddress>,
data: Option<Vec<u8>>,
data: Vec<Vec<u8>>,
}
impl SignableTransactionBuilderInternal {
// Takes in the change address so users don't miss that they have to manually set one
// If they don't, all leftover funds will become part of the fee
fn new(protocol: Protocol, fee: Fee, change_address: Option<MoneroAddress>) -> Self {
Self { protocol, fee, inputs: vec![], payments: vec![], change_address, data: None }
Self { protocol, fee, inputs: vec![], payments: vec![], change_address, data: vec![] }
}
fn add_input(&mut self, input: SpendableOutput) {
@@ -39,8 +42,8 @@ impl SignableTransactionBuilderInternal {
self.payments.extend(payments);
}
fn set_data(&mut self, data: Vec<u8>) {
self.data = Some(data);
fn add_data(&mut self, data: Vec<u8>) {
self.data.push(data);
}
}
@@ -100,9 +103,12 @@ impl SignableTransactionBuilder {
self.shallow_copy()
}
pub fn set_data(&mut self, data: Vec<u8>) -> Self {
self.0.write().unwrap().set_data(data);
self.shallow_copy()
pub fn add_data(&mut self, data: Vec<u8>) -> Result<Self, TransactionError> {
if data.len() > MAX_TX_EXTRA_NONCE_SIZE {
Err(TransactionError::TooMuchData)?;
}
self.0.write().unwrap().add_data(data);
Ok(self.shallow_copy())
}
pub fn build(self) -> Result<SignableTransaction, TransactionError> {

View File

@@ -24,7 +24,7 @@ use crate::{
rpc::{Rpc, RpcError},
wallet::{
address::MoneroAddress, SpendableOutput, Decoys, PaymentId, ExtraField, Extra, key_image_sort,
uniqueness, shared_key, commitment_mask, amount_encryption,
uniqueness, shared_key, commitment_mask, amount_encryption, extra::MAX_TX_EXTRA_NONCE_SIZE,
},
};
@@ -177,7 +177,7 @@ pub struct SignableTransaction {
protocol: Protocol,
inputs: Vec<SpendableOutput>,
payments: Vec<(MoneroAddress, u64)>,
data: Option<Vec<u8>>,
data: Vec<Vec<u8>>,
fee: u64,
}
@@ -191,7 +191,7 @@ impl SignableTransaction {
inputs: Vec<SpendableOutput>,
mut payments: Vec<(MoneroAddress, u64)>,
change_address: Option<MoneroAddress>,
data: Option<Vec<u8>>,
data: Vec<Vec<u8>>,
fee_rate: Fee,
) -> Result<SignableTransaction, TransactionError> {
// Make sure there's only one payment ID
@@ -220,8 +220,10 @@ impl SignableTransaction {
Err(TransactionError::NoOutputs)?;
}
if data.as_ref().map(|v| v.len()).unwrap_or(0) > 255 {
Err(TransactionError::TooMuchData)?;
for part in &data {
if part.len() > MAX_TX_EXTRA_NONCE_SIZE {
Err(TransactionError::TooMuchData)?;
}
}
// TODO TX MAX SIZE
@@ -313,8 +315,8 @@ impl SignableTransaction {
extra.push(ExtraField::Nonce(id_vec));
// Include data if present
if let Some(data) = self.data.take() {
extra.push(ExtraField::Nonce(data));
for part in self.data.drain(..) {
extra.push(ExtraField::Nonce(part));
}
let mut serialized = Vec::with_capacity(Extra::fee_weight(outputs.len(), self.data.as_ref()));