Skip to content

Commit

Permalink
fixed set serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
lisicky committed Jun 21, 2024
1 parent 27fe24c commit 2034cc2
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 30 deletions.
14 changes: 7 additions & 7 deletions rust/src/builders/batch_tools/witnesses_calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,14 @@ impl WitnessesCalculator {
}
};

TransactionWitnessSet {
TransactionWitnessSet::new_with_partial_dedup(
vkeys,
native_scripts: None,
bootstraps: bootstrap_keys,
plutus_scripts: None,
plutus_data: None,
redeemers: None,
}
None,
bootstrap_keys,
None,
None,
None,
)
}

fn add_vkey(&mut self) {
Expand Down
27 changes: 20 additions & 7 deletions rust/src/builders/certificates_builder.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use std::collections::BTreeMap;
use crate::*;

#[wasm_bindgen]
#[derive(Clone, Debug)]
pub struct CertificatesBuilder {
certs: Vec<(Certificate, Option<ScriptWitnessType>)>,
certs: BTreeMap<Certificate, Option<ScriptWitnessType>>,
}

#[wasm_bindgen]
impl CertificatesBuilder {
pub fn new() -> Self {
Self { certs: Vec::new() }
Self { certs: BTreeMap::new() }
}

pub fn add(&mut self, cert: &Certificate) -> Result<(), JsError> {
Expand All @@ -20,7 +21,11 @@ impl CertificatesBuilder {
));
}

self.certs.push((cert.clone(), None));
if self.certs.contains_key(cert) {
return Err(JsError::from_str("Certificate already exists"));
}

self.certs.insert(cert.clone(), None);
Ok(())
}

Expand All @@ -36,10 +41,14 @@ impl CertificatesBuilder {
));
}

self.certs.push((
if self.certs.contains_key(cert) {
return Err(JsError::from_str("Certificate already exists"));
}

self.certs.insert(
cert.clone(),
Some(ScriptWitnessType::PlutusScriptWitness(witness.clone())),
));
);
Ok(())
}

Expand All @@ -55,12 +64,16 @@ impl CertificatesBuilder {
));
}

self.certs.push((
if self.certs.contains_key(cert) {
return Err(JsError::from_str("Certificate already exists"));
}

self.certs.insert(
cert.clone(),
Some(ScriptWitnessType::NativeScriptWitness(
native_script_source.0.clone(),
)),
));
);
Ok(())
}

Expand Down
8 changes: 4 additions & 4 deletions rust/src/builders/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ pub(crate) fn fake_full_tx(
}
}

let witness_set = TransactionWitnessSet {
let witness_set = TransactionWitnessSet::new_with_partial_dedup(
vkeys,
native_scripts: tx_builder.get_combined_native_scripts(),
bootstraps: bootstrap_keys,
tx_builder.get_combined_native_scripts(),
bootstrap_keys,
plutus_scripts,
plutus_data,
redeemers,
};
);
Ok(Transaction {
body,
witness_set,
Expand Down
2 changes: 1 addition & 1 deletion rust/src/protocol_types/governance/voting_procedures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl_to_from!(VotingProcedures);

impl NoneOrEmpty for VotingProcedures {
fn is_none_or_empty(&self) -> bool {
self.0.is_empty()
self.0.is_empty() || self.0.values().all(|v| v.is_empty())
}
}

Expand Down
6 changes: 6 additions & 0 deletions rust/src/protocol_types/plutus/plutus_scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ pub struct PlutusScripts(pub(crate) Vec<PlutusScript>);

impl_to_from!(PlutusScripts);

impl NoneOrEmpty for PlutusScripts {
fn is_none_or_empty(&self) -> bool {
self.0.is_empty()
}
}

#[wasm_bindgen]
impl PlutusScripts {
pub fn new() -> Self {
Expand Down
5 changes: 4 additions & 1 deletion rust/src/protocol_types/witnesses/bootstrap_witnesses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ impl BootstrapWitnesses {
self.witnesses[index].clone()
}

pub fn add(&mut self, elem: &BootstrapWitness) {
pub fn add(&mut self, elem: &BootstrapWitness) -> Result<(), JsError> {
if self.dedup.insert(elem.clone()) {
self.witnesses.push(elem.clone());
Ok(())
} else {
Err(JsError::from_str("BootstrapWitnesses::add: duplicated element"))
}
}

Expand Down
28 changes: 28 additions & 0 deletions rust/src/protocol_types/witnesses/transaction_witnesses_set.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::*;
use crate::traits::EmptyToNone;

#[wasm_bindgen]
#[derive(Clone, Eq, PartialEq, Debug, serde::Serialize, serde::Deserialize, JsonSchema)]
Expand Down Expand Up @@ -81,4 +82,31 @@ impl TransactionWitnessSet {
redeemers: None,
}
}

pub(crate) fn new_with_partial_dedup(
vkeys: Option<Vkeywitnesses>,
native_scripts: Option<NativeScripts>,
bootstraps: Option<BootstrapWitnesses>,
plutus_scripts: Option<PlutusScripts>,
plutus_data: Option<PlutusList>,
redeemers: Option<Redeemers>,
) -> Self {
Self {
vkeys,
native_scripts: native_scripts
.map(|scripts| scripts.deduplicated_clone())
.empty_to_none()
.flatten(),
bootstraps,
plutus_scripts: plutus_scripts
.map(|scripts| scripts.deduplicated_clone())
.empty_to_none()
.flatten(),
plutus_data: plutus_data
.map(|data| data.deduplicated_clone())
.empty_to_none()
.flatten(),
redeemers,
}
}
}
5 changes: 4 additions & 1 deletion rust/src/protocol_types/witnesses/vkeywitnesses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ impl Vkeywitnesses {
self.witnesses[index].clone()
}

pub fn add(&mut self, elem: &Vkeywitness) {
pub fn add(&mut self, elem: &Vkeywitness) -> Result<(), JsError>{
if self.dedup.insert(elem.clone()) {
self.witnesses.push(elem.clone());
Ok(())
} else {
Err(JsError::from_str("Vkeywitnesses::add: duplicated element"))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ impl Serialize for Certificates {
&self,
serializer: &'se mut Serializer<W>,
) -> cbor_event::Result<&'se mut Serializer<W>> {
if self.0.is_empty() {
return Ok(serializer);
}
//TODO: uncomment this line when we conway ero will come
//serializer.write_tag(258)?;
let ordered_dedup = self.0.iter().collect::<BTreeSet<_>>();
serializer.write_array(cbor_event::Len::Len(self.0.len() as u64))?;
for element in &self.0 {
for element in ordered_dedup {
element.serialize(serializer)?;
}
Ok(serializer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ impl cbor_event::se::Serialize for VotingProposals {
&self,
serializer: &'se mut Serializer<W>,
) -> cbor_event::Result<&'se mut Serializer<W>> {
if self.0.is_empty() {
return Ok(serializer);
}
//TODO: uncomment this line when we conway ero will come
//serializer.write_tag(258)?;
let ordered_dedup = self.0.iter().collect::<BTreeSet<_>>();
serializer.write_array(cbor_event::Len::Len(self.0.len() as u64))?;
for element in &self.0 {
for element in ordered_dedup {
element.serialize(serializer)?;
}
Ok(serializer)
Expand Down
7 changes: 7 additions & 0 deletions rust/src/serialization/governance/voting_procedures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ impl cbor_event::se::Serialize for VotingProcedures {
&self,
serializer: &'se mut Serializer<W>,
) -> cbor_event::Result<&'se mut Serializer<W>> {
if self.is_none_or_empty() {
return Ok(serializer)
}

serializer.write_map(cbor_event::Len::Len(self.0.len() as u64))?;

for (voter, votes) in &self.0 {
if votes.is_empty() {
continue;
}
voter.serialize(serializer)?;
serializer.write_map(cbor_event::Len::Len(votes.len() as u64))?;
for (governance_action_id, voting_procedure) in votes {
Expand Down
6 changes: 3 additions & 3 deletions rust/src/serialization/plutus/plutus_scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ impl PlutusScripts {
Ok(serializer)
}

pub(crate) fn serialize_as_set<'se, W: Write>(
pub(crate) fn serialize_as_set_by_version<'se, W: Write>(
&self,
need_debuplication: bool,
need_deduplication: bool,
version: &Language,
serializer: &'se mut Serializer<W>,
) -> cbor_event::Result<&'se mut Serializer<W>> {
//TODO: uncomment this line when we conway ero will come
//serializer.write_tag(258)?;
let view = match need_debuplication {
let view = match need_deduplication {
true => self.deduplicated_view(Some(version)),
false => self.view(version),
};
Expand Down
8 changes: 5 additions & 3 deletions rust/src/serialization/witnesses/transaction_witnesses_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,20 @@ impl cbor_event::se::Serialize for TransactionWitnessSet {
field.serialize(serializer)?;
}
}

//no need deduplication here because transaction witness set already has deduplicated plutus scripts
if let Some(plutus_scripts) = &self.plutus_scripts {
if has_plutus_v1 {
serializer.write_unsigned_integer(3)?;
plutus_scripts.serialize_by_version(&Language::new_plutus_v1(), serializer)?;
plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v1(), serializer)?;
}
if has_plutus_v2 {
serializer.write_unsigned_integer(6)?;
plutus_scripts.serialize_by_version(&Language::new_plutus_v2(), serializer)?;
plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v2(), serializer)?;
}
if has_plutus_v3 {
serializer.write_unsigned_integer(7)?;
plutus_scripts.serialize_by_version(&Language::new_plutus_v3(), serializer)?;
plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v3(), serializer)?;
}
}
if let Some(field) = &self.plutus_data {
Expand Down
19 changes: 18 additions & 1 deletion rust/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ pub trait NoneOrEmpty {
fn is_none_or_empty(&self) -> bool;
}

pub trait EmptyToNone: Sized {
fn empty_to_none(self) -> Option<Self>;
}

impl<T: NoneOrEmpty> NoneOrEmpty for &T {
fn is_none_or_empty(&self) -> bool {
(*self).is_none_or_empty()
Expand All @@ -10,6 +14,19 @@ impl<T: NoneOrEmpty> NoneOrEmpty for &T {

impl<T: NoneOrEmpty> NoneOrEmpty for Option<T> {
fn is_none_or_empty(&self) -> bool {
self.is_none() || self.as_ref().unwrap().is_none_or_empty()
match &self {
Some(x) => x.is_none_or_empty(),
None => true,
}
}
}

impl<T: NoneOrEmpty> EmptyToNone for T {
fn empty_to_none(self) -> Option<Self> {
if self.is_none_or_empty() {
None
} else {
Some(self)
}
}
}

0 comments on commit 2034cc2

Please sign in to comment.