From 9eb934589f99e42ed0adcdee241a6375a0471dc1 Mon Sep 17 00:00:00 2001 From: lisicky Date: Sun, 1 Sep 2024 22:04:11 +0900 Subject: [PATCH 01/19] fix script data hash for empty redeemers --- rust/src/tests/plutus.rs | 18 ++++++++++++++++++ rust/src/utils.rs | 7 ++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/rust/src/tests/plutus.rs b/rust/src/tests/plutus.rs index 4e0ae3dc..05177e63 100644 --- a/rust/src/tests/plutus.rs +++ b/rust/src/tests/plutus.rs @@ -573,4 +573,22 @@ fn datum_from_base_key_script_address() { let orig_datum = PlutusData::from_json("{\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"bytes\": \"88ac6bd19c1a17ed88051b1586536cd1cc408be21efb7ada33be6afd\"}]}, {\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"constructor\": 1, \"fields\": [{\"bytes\": \"dc3b534f7621f6c83304bbb99e0f44ca168c3f0932b1b521ee0030a6\"}]}]}]}]}", PlutusDatumSchema::DetailedSchema).unwrap(); assert_eq!(datum, orig_datum); +} + +#[test] +fn script_data_hash_no_redeemers() { + let datum = PlutusData::from_hex("d8799fd8799fd8799f581c7fbb4763847b9ec49a132d5359bd86aaecde9275a03aef294ffb79d0ffd8799fd8799fd8799f581cfa34f3b651ecb6a75834c80dc1fd162feb1d1b4cdcef0d065a5785aaffffffffd8799fd8799f581c7fbb4763847b9ec49a132d5359bd86aaecde9275a03aef294ffb79d0ffd8799fd8799fd8799f581cfa34f3b651ecb6a75834c80dc1fd162feb1d1b4cdcef0d065a5785aaffffffffd87a80d8799fd8799f4040ff1a059eb214ff1a001e84801a001e8480ff") + .unwrap(); + let mut list = PlutusList::from(vec![datum]); + list.definite_encoding = Some(false); + + let hash = hash_script_data( + &Redeemers::new(), + &Costmdls::new(), + Some(list), + ); + assert_eq!( + hex::encode(hash.to_bytes()), + "5f4e4b313590ed119c077f2ef78ff294118e7955c63982e304a791831238baf4" + ); } \ No newline at end of file diff --git a/rust/src/utils.rs b/rust/src/utils.rs index 1b0804cf..86cbdb55 100644 --- a/rust/src/utils.rs +++ b/rust/src/utils.rs @@ -600,10 +600,11 @@ pub fn hash_script_data( /* ; Finally, note that in the case that a transaction includes datums but does not ; include any redeemers, the script data format becomes (in hex): - ; [ 80 | datums | A0 ] - ; corresponding to a CBOR empty list and an empty map (our apologies). + ; [ A0 | datums | A0 ] + ; corresponding to a CBOR empty map and an empty map (our apologies). + ; Before Conway first structure was an empty list, but it was changed to empty map since Conway. */ - buf.push(0x80); + buf.push(0xA0); if let Some(d) = &datums { buf.extend(d.to_set_bytes()); } From d86ce387e992f66093ab1dcee972650110d48192 Mon Sep 17 00:00:00 2001 From: lisicky Date: Sun, 1 Sep 2024 22:04:25 +0900 Subject: [PATCH 02/19] fix naming --- rust/src/protocol_types/plutus/plutus_data.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/src/protocol_types/plutus/plutus_data.rs b/rust/src/protocol_types/plutus/plutus_data.rs index fcc4f97a..ad2cdc44 100644 --- a/rust/src/protocol_types/plutus/plutus_data.rs +++ b/rust/src/protocol_types/plutus/plutus_data.rs @@ -501,13 +501,13 @@ impl PlutusList { pub(crate) fn deduplicated_view(&self) -> Vec<&PlutusData> { let mut dedup = BTreeSet::new(); - let mut keyhashes = Vec::new(); + let mut datas = Vec::new(); for elem in &self.elems { if dedup.insert(elem) { - keyhashes.push(elem); + datas.push(elem); } } - keyhashes + datas } pub(crate) fn to_set_bytes(&self) -> Vec { From 765c1b4b56f6a36a5fb00d61aaddbcc77ec900f7 Mon Sep 17 00:00:00 2001 From: lisicky Date: Sun, 1 Sep 2024 22:07:53 +0900 Subject: [PATCH 03/19] bump version --- package-lock.json | 4 ++-- package.json | 2 +- rust/Cargo.toml | 2 +- rust/json-gen/Cargo.lock | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index a9dc2d0e..d2506b91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cardano-serialization-lib", - "version": "12.0.1", + "version": "12.0.2-beta.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cardano-serialization-lib", - "version": "12.0.1", + "version": "12.0.2-beta.1", "hasInstallScript": true, "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index 76f099ee..11279965 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cardano-serialization-lib", - "version": "12.0.1", + "version": "12.0.2-beta.1", "description": "(De)serialization functions for the Cardano blockchain along with related utility functions", "scripts": { "rust:build-nodejs": "(rimraf ./rust/pkg && cd rust; wasm-pack build --target=nodejs; cd ..; npm run js:ts-json-gen; cd rust; wasm-pack pack) && npm run js:flowgen", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 544afa81..a8fadb13 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cardano-serialization-lib" -version = "12.0.1" +version = "12.0.2-beta.1" edition = "2018" authors = ["EMURGO"] license = "MIT" diff --git a/rust/json-gen/Cargo.lock b/rust/json-gen/Cargo.lock index 32311042..94b02c1a 100644 --- a/rust/json-gen/Cargo.lock +++ b/rust/json-gen/Cargo.lock @@ -49,7 +49,7 @@ checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "cardano-serialization-lib" -version = "12.0.1" +version = "12.0.2-beta.1" dependencies = [ "bech32", "cbor_event", From c7682ab6b863c746fba704caf8d481c879b189d7 Mon Sep 17 00:00:00 2001 From: lisicky Date: Tue, 3 Sep 2024 16:33:58 +0900 Subject: [PATCH 04/19] add "set" tag as default for serialization --- .../builders/batch_tools/cbor_calculator.rs | 38 ++++++++++++++++++- .../batch_tools/witnesses_calculator.rs | 16 ++++---- .../certificates/certificates_collection.rs | 3 +- rust/src/serialization/credentials.rs | 3 +- rust/src/serialization/ed25519_key_hashes.rs | 3 +- .../governance/proposals/voting_proposals.rs | 3 +- rust/src/serialization/native_scripts.rs | 3 +- rust/src/serialization/plutus/plutus_data.rs | 3 +- .../serialization/plutus/plutus_scripts.rs | 3 +- rust/src/serialization/tx_inputs.rs | 3 +- .../witnesses/bootstrap_witnesses.rs | 3 +- .../serialization/witnesses/vkeywitnesses.rs | 3 +- rust/src/tests/builders/tx_builder.rs | 28 +++++++------- rust/src/tests/fees.rs | 20 +++++----- rust/src/tests/plutus.rs | 10 ++--- rust/src/tests/utils.rs | 4 +- 16 files changed, 85 insertions(+), 61 deletions(-) diff --git a/rust/src/builders/batch_tools/cbor_calculator.rs b/rust/src/builders/batch_tools/cbor_calculator.rs index fec45147..83ebc1cd 100644 --- a/rust/src/builders/batch_tools/cbor_calculator.rs +++ b/rust/src/builders/batch_tools/cbor_calculator.rs @@ -26,6 +26,17 @@ impl CborCalculator { } } + pub(super) fn get_wrapped_struct_size(items_count: u64) -> usize { + //wrapped struct is a struct of 2 elements, tag and value + let tag_size = CborCalculator::get_tag_size(258); + let value_size = CborCalculator::get_struct_size(items_count); + tag_size + value_size + } + + pub(super) fn get_tag_size(tag: u64) -> usize { + Self::get_struct_size(tag) + } + pub(super) fn get_coin_size(coin: &Coin) -> usize { Self::get_struct_size(coin.clone().into()) } @@ -71,12 +82,35 @@ impl CborCalculator { pub(super) fn get_bare_tx_body_size(body_fields: &HashSet) -> usize { let mut size = CborCalculator::get_struct_size(body_fields.len() as u64); for field in body_fields { - size += CborCalculator::get_struct_size(field.to_u64().unwrap()); + let wrapped = match field { + TxBodyNames::Inputs => true, + TxBodyNames::Outputs => false, + TxBodyNames::Fee => false, + TxBodyNames::Ttl => false, + TxBodyNames::Certs => true, + TxBodyNames::Withdrawals => false, + TxBodyNames::Update => false, + TxBodyNames::AuxiliaryDataHash => false, + TxBodyNames::ValidityStartInterval => false, + TxBodyNames::Mint => false, + TxBodyNames::ScriptDataHash => false, + TxBodyNames::Collateral => true, + TxBodyNames::RequiredSigners => true, + TxBodyNames::NetworkId => false, + TxBodyNames::CollateralReturn => false, + TxBodyNames::TotalCollateral => false, + TxBodyNames::ReferenceInputs => true, + }; + if wrapped { + size += CborCalculator::get_wrapped_struct_size(field.to_u64().unwrap()); + } else { + size += CborCalculator::get_struct_size(field.to_u64().unwrap()); + } } size } - pub(super) fn get_wintnesses_set_struct_size( + pub(super) fn get_witnesses_set_struct_size( witnesses_fields: &HashSet, ) -> usize { let mut size = CborCalculator::get_struct_size(witnesses_fields.len() as u64); diff --git a/rust/src/builders/batch_tools/witnesses_calculator.rs b/rust/src/builders/batch_tools/witnesses_calculator.rs index b0c50614..62a5a1eb 100644 --- a/rust/src/builders/batch_tools/witnesses_calculator.rs +++ b/rust/src/builders/batch_tools/witnesses_calculator.rs @@ -144,18 +144,18 @@ impl WitnessesCalculator { if self.vkeys_count == 0 { if self.used_fields.len() > 0 { self.total_size -= - CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); + CborCalculator::get_witnesses_set_struct_size(&self.used_fields); } self.used_fields.insert(WitnessSetNames::Vkeys); - self.total_size += CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); + self.total_size += CborCalculator::get_witnesses_set_struct_size(&self.used_fields); } if self.vkeys_count != 0 { - self.total_size -= CborCalculator::get_struct_size(self.vkeys_count); + self.total_size -= CborCalculator::get_wrapped_struct_size(self.vkeys_count); } self.vkeys_count += 1; - self.total_size += CborCalculator::get_struct_size(self.vkeys_count); + self.total_size += CborCalculator::get_wrapped_struct_size(self.vkeys_count); self.total_size += CborCalculator::get_fake_vkey_size(); } @@ -164,18 +164,18 @@ impl WitnessesCalculator { if self.boostrap_count == 0 { if self.used_fields.len() > 0 { self.total_size -= - CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); + CborCalculator::get_witnesses_set_struct_size(&self.used_fields); } self.used_fields.insert(WitnessSetNames::Bootstraps); - self.total_size += CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); + self.total_size += CborCalculator::get_witnesses_set_struct_size(&self.used_fields); } if self.boostrap_count != 0 { - self.total_size -= CborCalculator::get_struct_size(self.boostrap_count); + self.total_size -= CborCalculator::get_wrapped_struct_size(self.boostrap_count); } self.boostrap_count += 1; - self.total_size += CborCalculator::get_struct_size(self.boostrap_count); + self.total_size += CborCalculator::get_wrapped_struct_size(self.boostrap_count); self.total_size += CborCalculator::get_boostrap_witness_size(address); } } diff --git a/rust/src/serialization/certificates/certificates_collection.rs b/rust/src/serialization/certificates/certificates_collection.rs index 06b12c7e..f4beb222 100644 --- a/rust/src/serialization/certificates/certificates_collection.rs +++ b/rust/src/serialization/certificates/certificates_collection.rs @@ -6,8 +6,7 @@ impl Serialize for Certificates { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; serializer.write_array(Len::Len(self.len() as u64))?; for element in &self.certs { element.serialize(serializer)?; diff --git a/rust/src/serialization/credentials.rs b/rust/src/serialization/credentials.rs index a45086fb..5c83a851 100644 --- a/rust/src/serialization/credentials.rs +++ b/rust/src/serialization/credentials.rs @@ -6,8 +6,7 @@ impl cbor_event::se::Serialize for Credentials { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in self.to_vec() { element.serialize(serializer)?; diff --git a/rust/src/serialization/ed25519_key_hashes.rs b/rust/src/serialization/ed25519_key_hashes.rs index 46d6a73e..232c4c61 100644 --- a/rust/src/serialization/ed25519_key_hashes.rs +++ b/rust/src/serialization/ed25519_key_hashes.rs @@ -6,8 +6,7 @@ impl Serialize for Ed25519KeyHashes { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in self.to_vec() { element.serialize(serializer)?; diff --git a/rust/src/serialization/governance/proposals/voting_proposals.rs b/rust/src/serialization/governance/proposals/voting_proposals.rs index 64ee941a..53b967ce 100644 --- a/rust/src/serialization/governance/proposals/voting_proposals.rs +++ b/rust/src/serialization/governance/proposals/voting_proposals.rs @@ -6,8 +6,7 @@ impl cbor_event::se::Serialize for VotingProposals { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in &self.proposals { element.serialize(serializer)?; diff --git a/rust/src/serialization/native_scripts.rs b/rust/src/serialization/native_scripts.rs index 8b3f5e7b..3cf2bdad 100644 --- a/rust/src/serialization/native_scripts.rs +++ b/rust/src/serialization/native_scripts.rs @@ -20,8 +20,7 @@ impl NativeScripts { need_deduplication: bool, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; if need_deduplication { let view = self.deduplicated_view(); serializer.write_array(cbor_event::Len::Len(self.0.len() as u64))?; diff --git a/rust/src/serialization/plutus/plutus_data.rs b/rust/src/serialization/plutus/plutus_data.rs index f3ce5f64..6c806cb2 100644 --- a/rust/src/serialization/plutus/plutus_data.rs +++ b/rust/src/serialization/plutus/plutus_data.rs @@ -243,8 +243,7 @@ impl PlutusList { need_deduplication: bool, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; let use_definite_encoding = match self.definite_encoding { Some(definite) => definite, None => self.elems.is_empty(), diff --git a/rust/src/serialization/plutus/plutus_scripts.rs b/rust/src/serialization/plutus/plutus_scripts.rs index 37f30906..ab0832b0 100644 --- a/rust/src/serialization/plutus/plutus_scripts.rs +++ b/rust/src/serialization/plutus/plutus_scripts.rs @@ -34,8 +34,7 @@ impl PlutusScripts { version: &Language, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; let view = match need_deduplication { true => self.deduplicated_view(Some(version)), false => self.view(version), diff --git a/rust/src/serialization/tx_inputs.rs b/rust/src/serialization/tx_inputs.rs index 7fcc683d..7d6e1350 100644 --- a/rust/src/serialization/tx_inputs.rs +++ b/rust/src/serialization/tx_inputs.rs @@ -6,8 +6,7 @@ impl cbor_event::se::Serialize for TransactionInputs { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in &self.inputs { element.serialize(serializer)?; diff --git a/rust/src/serialization/witnesses/bootstrap_witnesses.rs b/rust/src/serialization/witnesses/bootstrap_witnesses.rs index d4d4464c..3f4f7a98 100644 --- a/rust/src/serialization/witnesses/bootstrap_witnesses.rs +++ b/rust/src/serialization/witnesses/bootstrap_witnesses.rs @@ -10,8 +10,7 @@ impl cbor_event::se::Serialize for BootstrapWitnesses { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.get_vec_wits().len() as u64))?; for element in self.get_vec_wits() { element.serialize(serializer)?; diff --git a/rust/src/serialization/witnesses/vkeywitnesses.rs b/rust/src/serialization/witnesses/vkeywitnesses.rs index f3190569..ddf4c92a 100644 --- a/rust/src/serialization/witnesses/vkeywitnesses.rs +++ b/rust/src/serialization/witnesses/vkeywitnesses.rs @@ -10,8 +10,7 @@ impl cbor_event::se::Serialize for Vkeywitnesses { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - //TODO: uncomment this line when we conway ero will come - //serializer.write_tag(258)?; + serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.witnesses.len() as u64))?; for element in &self.witnesses { element.serialize(serializer)?; diff --git a/rust/src/tests/builders/tx_builder.rs b/rust/src/tests/builders/tx_builder.rs index 22c2b8f4..1a36c543 100644 --- a/rust/src/tests/builders/tx_builder.rs +++ b/rust/src/tests/builders/tx_builder.rs @@ -98,7 +98,7 @@ fn build_tx_with_change() { .checked_add(&Value::new(&tx_builder.get_fee_if_set().unwrap())) .unwrap() ); - assert_eq!(tx_builder.full_size().unwrap(), 285); + assert_eq!(tx_builder.full_size().unwrap(), 291); assert_eq!(tx_builder.output_sizes(), vec![62, 65]); let _final_tx = tx_builder.build(); // just test that it doesn't throw } @@ -172,7 +172,7 @@ fn build_tx_with_change_with_datum() { .checked_add(&Value::new(&tx_builder.get_fee_if_set().unwrap())) .unwrap() ); - assert_eq!(tx_builder.full_size().unwrap(), 319); + assert_eq!(tx_builder.full_size().unwrap(), 325); assert_eq!(tx_builder.output_sizes(), vec![62, 99]); let _final_tx = tx_builder.build(); // just test that it doesn't throw } @@ -304,8 +304,8 @@ fn build_tx_with_certs() { ) .to_address(); tx_builder.add_change_if_needed(&change_addr).unwrap(); - assert_eq!(tx_builder.min_fee().unwrap().to_str(), "214002"); - assert_eq!(tx_builder.get_fee_if_set().unwrap().to_str(), "214002"); + assert_eq!(tx_builder.min_fee().unwrap().to_str(), "218502"); + assert_eq!(tx_builder.get_fee_if_set().unwrap().to_str(), "218502"); assert_eq!(tx_builder.get_deposit().unwrap().to_str(), "1000000"); assert_eq!(tx_builder.outputs.len(), 1); assert_eq!( @@ -559,7 +559,7 @@ fn build_tx_with_inputs() { ) .unwrap() .to_str(), - "69500" + "71000" ); tx_builder.add_regular_input( &EnterpriseAddress::new(NetworkInfo::testnet_preprod().network_id(), &spend_cred) @@ -1592,7 +1592,7 @@ fn build_tx_with_native_assets_change_and_no_purification_cuz_not_enough_pure_co ); // The single change output contains more Coin then minimal utxo value // But not enough to cover the additional fee for a separate output - assert_eq!(final_tx.outputs().get(1).amount().coin(), BigNum(499)); + assert_eq!(final_tx.outputs().get(1).amount().coin(), BigNum(493)); } #[test] @@ -2512,7 +2512,7 @@ fn tx_builder_cip2_random_improve_adds_enough_for_fees() { .unwrap(), ) .unwrap(); - assert_eq!(tx_builder.min_fee().unwrap(), BigNum(53)); + assert_eq!(tx_builder.min_fee().unwrap(), BigNum(56)); let mut available_inputs = TransactionUnspentOutputs::new(); available_inputs.add(&make_input(1u8, Value::new(&BigNum(150)))); available_inputs.add(&make_input(2u8, Value::new(&BigNum(150)))); @@ -2520,7 +2520,7 @@ fn tx_builder_cip2_random_improve_adds_enough_for_fees() { let add_inputs_res = tx_builder.add_inputs_from(&available_inputs, CoinSelectionStrategyCIP2::RandomImprove); assert!(add_inputs_res.is_ok(), "{:?}", add_inputs_res.err()); - assert_eq!(tx_builder.min_fee().unwrap(), BigNum(264)); + assert_eq!(tx_builder.min_fee().unwrap(), BigNum(270)); let change_addr = ByronAddress::from_base58("Ae2tdPwUPEZGUEsuMAhvDcy94LKsZxDjCbgaiBBMgYpR8sKf96xJmit7Eho") .unwrap() @@ -3529,7 +3529,7 @@ fn add_mint_includes_witnesses_into_fee_estimation() { // Original tx fee now assumes two VKey signatures for two inputs let original_tx_fee = tx_builder.min_fee().unwrap(); - assert_eq!(original_tx_fee, BigNum(168361)); + assert_eq!(original_tx_fee, BigNum(168625)); // Add minting four assets from three different policies tx_builder.add_mint_asset(&mint_script1, &name1, &amount).expect("Failed to add mint asset"); @@ -3555,7 +3555,7 @@ fn add_mint_includes_witnesses_into_fee_estimation() { .unwrap(); assert_eq!(raw_mint_fee, BigNum(5544)); - assert_eq!(raw_mint_script_fee, BigNum(4312)); + assert_eq!(raw_mint_script_fee, BigNum(4444)); let new_tx_fee = tx_builder.min_fee().unwrap(); @@ -4364,10 +4364,10 @@ fn test_ex_unit_costs_are_added_to_the_fees() { tx_builder.get_fee_if_set().unwrap() } - assert_eq!(calc_fee_with_ex_units(0, 0), BigNum(173509)); - assert_eq!(calc_fee_with_ex_units(10000, 0), BigNum(174174)); - assert_eq!(calc_fee_with_ex_units(0, 10000000), BigNum(174406)); - assert_eq!(calc_fee_with_ex_units(10000, 10000000), BigNum(175071)); + assert_eq!(calc_fee_with_ex_units(0, 0), BigNum(174169)); + assert_eq!(calc_fee_with_ex_units(10000, 0), BigNum(174834)); + assert_eq!(calc_fee_with_ex_units(0, 10000000), BigNum(175066)); + assert_eq!(calc_fee_with_ex_units(10000, 10000000), BigNum(175731)); } #[test] diff --git a/rust/src/tests/fees.rs b/rust/src/tests/fees.rs index 04de0d19..bc19fb6f 100644 --- a/rust/src/tests/fees.rs +++ b/rust/src/tests/fees.rs @@ -55,11 +55,11 @@ fn tx_simple_utxo() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00016f32030aa10081825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee5840fae5de40c94d759ce13bf9886262159c4f26a289fd192e165995b785259e503f6887bf39dfa23a47cf163784c6eee23f61440e749bc1df3c73975f5231aeda0ff5f6" + "84a400d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00016f32030aa100d9010281825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee58406d68d8b7b2ee54f1f46b64e3f61a14f840be2ec125c858ec917f634a1eb898a51660654839226016a2588d39920e6dfe1b66d917027f198b5eb887d20f4ac805f5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "94502" // todo: compare to Haskell fee to make sure the diff is not too big + "97502" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -109,11 +109,11 @@ fn tx_simple_byron_utxo() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a0001b582030aa10281845820473811afd4d939b337c9be1a2ceeb2cb2c75108bddf224c5c21c51592a7b204a5840f0b04a852353eb23b9570df80b2aa6a61b723341ab45a2024a05b07cf58be7bdfbf722c09040db6cee61a0d236870d6ad1e1349ac999ec0db28f9471af25fb0c5820c8b95d0d35fe75a70f9f5633a3e2439b2994b9e2bc851c49e9f91d1a5dcbb1a341a0f5f6" + "84a400d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a0001b582030aa102d9010281845820473811afd4d939b337c9be1a2ceeb2cb2c75108bddf224c5c21c51592a7b204a58408b4ca7a71340bc6441f0e390122d53aba154b7e2b432ec2927ed8db7395d3d9347989aa1fca4823c991c1ef309570a0bbdf62155e3dba376fae9827cb465f5055820c8b95d0d35fe75a70f9f5633a3e2439b2994b9e2bc851c49e9f91d1a5dcbb1a341a0f5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "112502" // todo: compare to Haskell fee to make sure the diff is not too big + "115502" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -196,11 +196,11 @@ fn tx_multi_utxo() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a400828258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7182a82582082839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace3207018282581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c19012182581d61bcd18fcffa797c16c007014e2b8553b8b9b1e94c507688726243d6111a3420989c021a0002ccce031903e7a10082825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee58401ec3e56008650282ba2e1f8a20e81707810b2d0973c4d42a1b4df65b732bda81567c7824904840b2554d2f33861da5d70588a29d33b2b61042e3c3445301d8008258206872b0a874acfe1cace12b20ea348559a7ecc912f2fc7f674f43481df973d92c5840a0718fb5b37d89ddf926c08e456d3f4c7f749e91f78bb3e370751d5b632cbd20d38d385805291b1ef2541b02543728a235e01911f4b400bfb50e5fce589de907f5f6" + "84a400d90102828258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7182a82582082839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace3207018282581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c19012182581d61bcd18fcffa797c16c007014e2b8553b8b9b1e94c507688726243d6111a3420989c021a0002ccce031903e7a100d9010282825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee584082eea9c7848c1136ebcb5fd5774d8dfc330c63b7f44b56a5cc5008887d3923df8785ebab92c230114099cf9b79a6c6c57ead026fa495d526731cc00caa3407088258206872b0a874acfe1cace12b20ea348559a7ecc912f2fc7f674f43481df973d92c5840f8861b68b3f966b6b63cbd3f7abf18efa18620aee9e730dea75d2d1cb0668988486f852f7743f6b5cc841c62d11440073706b52b408c0d776a411e2a0dd0da0af5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "184002" // todo: compare to Haskell fee to make sure the diff is not too big + "187002" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -317,11 +317,11 @@ fn tx_register_stake() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00040f12030a04818a03581c1c13374874c68016df54b1339b6cacdd801098431e7659b24928efc15820bd0000f498ccacdc917c28274cba51c415f3f21931ff41ca8dc1197499f8e1241a000f42401a000f4240d81e82031864581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af7081581c51df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af7080f6a10083825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee5840a7f305d7e46abfe0f7bea6098bdf853ab9ce8e7aa381be5a991a871852f895a718e20614e22be43494c4dc3a8c78c56cd44fd38e0e5fff3e2fbd19f70402fc02825820b24c040e65994bd5b0621a060166d32d356ef4be3cc1f848426a4cf386887089584013c372f82f1523484eab273241d66d92e1402507760e279480912aa5f0d88d656d6f25d41e65257f2f38c65ac5c918a6735297741adfc718394994f20a1cfd0082582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840d326b993dfec21b9b3e1bd2f80adadc2cd673a1d8d033618cc413b0b02bc3b7efbb23d1ff99138abd05c398ce98e7983a641b50dcf0f64ed33f26c6e636b0b0ff5f6" + "84a500d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00040f12030a04d90102818a03581c1c13374874c68016df54b1339b6cacdd801098431e7659b24928efc15820bd0000f498ccacdc917c28274cba51c415f3f21931ff41ca8dc1197499f8e1241a000f42401a000f4240d81e82031864581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af70d9010281581c51df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af7080f6a100d9010283825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee584081e223791960a07f401c378dce048ea658a155510ae6541c6cb692ed41ee45b40b913d1428a94af145885639f8acf99549f7b29af1e34997b9cb8ad05fe6e50a825820b24c040e65994bd5b0621a060166d32d356ef4be3cc1f848426a4cf38688708958401a246b6a4d63e83bd4904ac3b787797ba54238aab8e733b75b5ab2e465c46fce67e4403169a53239e7036f87f0518ec4414a10e45a1aa1788322d2777f59c30182582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840ea9518346e8515aea6c16e7076a1d0a637582f736c0b65abd1f4adccd8920f2da699e8602029cc608da2ba46b6a6e61f41166b12ae17c922114c040facd90b07f5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "269502" // todo: compare to Haskell fee to make sure the diff is not too big + "275502" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -529,11 +529,11 @@ fn tx_withdrawal() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00027ac6030a05a1581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af70190539a10082825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee5840fc0493f7121efe385d72830680e735ccdef99c3a31953fe877b89ad3a97fcdb871cc7f2cdd6a8104e52f6963bd9e10d814d4fabdbcdc8475bc63e872dcc94d0a82582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840a051ba927582004aedab736b9f1f9330ff867c260f4751135d480074256e83cd23d2a4bb109f955c43afdcdc5d1841b28d5c1ea2148dfbb6252693590692bb00f5f6" + "84a500d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00027ac6030a05a1581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af70190539a100d9010282825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee58406dda4d88a17c7b888d15eb29f0871e85f3c50e1ea4efcc0d7781f4db0ae11dd418abae42f7f62637cc54d21887ccb60dc3ccae545e7a25c7c553b3a91e9e6d0082582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840a24b4863189d5872fdb98529bbe6feae375031162786bda1244d73c54adafea0ace2f087f23a794af4f232651ba66071246ab5bc1e1b0b9a39044d0531eeac0ef5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "163002" // todo: compare to Haskell fee to make sure the diff is not too big + "166002" // todo: compare to Haskell fee to make sure the diff is not too big ); } diff --git a/rust/src/tests/plutus.rs b/rust/src/tests/plutus.rs index 05177e63..ac57c7f2 100644 --- a/rust/src/tests/plutus.rs +++ b/rust/src/tests/plutus.rs @@ -40,13 +40,13 @@ pub fn plutus_list_serialization_cli_compatibility() { // witness_set should have fixed length array let mut witness_set = TransactionWitnessSet::new(); witness_set.set_plutus_data(&list); - assert_eq!("a1049f01ff", hex::encode(witness_set.to_bytes())); + assert_eq!("a104d901029f01ff", hex::encode(witness_set.to_bytes())); list = PlutusList::new(); list.add(&datum); witness_set.set_plutus_data(&list); assert_eq!( - format!("a1049f{}ff", datum_cli), + format!("a104d901029f{}ff", datum_cli), hex::encode(witness_set.to_bytes()) ); } @@ -436,7 +436,7 @@ fn test_known_plutus_data_hash() { let hash = hash_script_data(&redeemers, &retained_cost_models, Some(pdata)); assert_eq!( hex::encode(hash.to_bytes()), - "2fd8b7e248b376314d02989c885c278796ab0e1d6e8aa0cb91f562ff5f7dbd70" + "296c56ac50bc55b35daa782d11bd35fea58246ce494752bb03a62602aa855a1a" ); } @@ -515,7 +515,7 @@ fn test_known_plutus_data_hash_2() { ); assert_eq!( hex::encode(hash.to_bytes()), - "0a076247a05aacbecf72ea15b94e3d0331b21295a08d9ab7b8675c13840563a6" + "09bd438e74c7d46bf4e3f29d44220cca441dc11514ab66ba45a9ad7f902b749e" ); } @@ -589,6 +589,6 @@ fn script_data_hash_no_redeemers() { ); assert_eq!( hex::encode(hash.to_bytes()), - "5f4e4b313590ed119c077f2ef78ff294118e7955c63982e304a791831238baf4" + "fd53a28a846ae6ccf8b221d03d4af122b0b3c442089c05b87e3d86c6792b3ef0" ); } \ No newline at end of file diff --git a/rust/src/tests/utils.rs b/rust/src/tests/utils.rs index c8dabac1..a8c629ca 100644 --- a/rust/src/tests/utils.rs +++ b/rust/src/tests/utils.rs @@ -459,7 +459,7 @@ fn correct_script_data_hash() { assert_eq!( hex::encode(script_data_hash.to_bytes()), - "4415e6667e6d6bbd992af5092d48e3c2ba9825200d0234d2470068f7f0f178b3" + "1701ce6560526f52bbaa96e49b6f07f3646f3ac2d901b5a38be9a5ee946f7f8a" ); } @@ -733,7 +733,7 @@ fn test_vasil_v1_costmodel_hashing() { ); assert_eq!( hex::encode(hash.to_bytes()), - "887e1b6416d750d871c0f5b7136b54f7b8e8b0e293379d090f38f8f821d08a29" + "c682f77e8adcb58d6db4cd50e342aa452e70c650f67ef35debb1f46327521555" ); } From bf3137ebc86206e27f8719ba6afae6c3b44c912a Mon Sep 17 00:00:00 2001 From: lisicky Date: Wed, 4 Sep 2024 04:34:24 +0900 Subject: [PATCH 05/19] add functions to tx signing to FixedTransaction --- rust/src/protocol_types/fixed_tx.rs | 64 ++- .../witnesses/fixed_tx_witnesses_set.rs | 35 ++ rust/src/protocol_types/witnesses/mod.rs | 4 + .../witnesses/transaction_witnesses_set.rs | 26 + rust/src/serialization/fixed_tx.rs | 12 +- .../witnesses/fixed_tx_witnesses_set.rs | 25 + rust/src/serialization/witnesses/mod.rs | 3 +- .../witnesses/transaction_witnesses_set.rs | 499 ++++++++++-------- rust/src/tests/protocol_types/fixed_tx.rs | 10 +- 9 files changed, 436 insertions(+), 242 deletions(-) create mode 100644 rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs create mode 100644 rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs diff --git a/rust/src/protocol_types/fixed_tx.rs b/rust/src/protocol_types/fixed_tx.rs index 8733ed91..e79879cb 100644 --- a/rust/src/protocol_types/fixed_tx.rs +++ b/rust/src/protocol_types/fixed_tx.rs @@ -5,9 +5,9 @@ use crate::*; pub struct FixedTransaction { pub(crate) body: TransactionBody, pub(crate) body_bytes: Vec, + pub(crate) tx_hash: TransactionHash, - pub(crate) witness_set: TransactionWitnessSet, - pub(crate) witness_bytes: Vec, + pub(crate) witness_set: FixedTxWitnessesSet, pub(crate) is_valid: bool, @@ -25,13 +25,14 @@ impl FixedTransaction { is_valid: bool, ) -> Result { let body = TransactionBody::from_bytes(raw_body.to_vec())?; - let witness_set = TransactionWitnessSet::from_bytes(raw_witness_set.to_vec())?; + let witness_set = FixedTxWitnessesSet::from_bytes(raw_witness_set.to_vec())?; + let tx_hash = TransactionHash::from(blake2b256(raw_body)); Ok(FixedTransaction { body, body_bytes: raw_body.to_vec(), + tx_hash, witness_set, - witness_bytes: raw_witness_set.to_vec(), is_valid, auxiliary_data: None, auxiliary_bytes: None, @@ -45,20 +46,42 @@ impl FixedTransaction { is_valid: bool, ) -> Result { let body = TransactionBody::from_bytes(raw_body.to_vec())?; - let witness_set = TransactionWitnessSet::from_bytes(raw_witness_set.to_vec())?; + let witness_set = FixedTxWitnessesSet::from_bytes(raw_witness_set.to_vec())?; + let tx_hash = TransactionHash::from(blake2b256(raw_body)); let auxiliary_data = Some(AuxiliaryData::from_bytes(raw_auxiliary_data.to_vec())?); Ok(FixedTransaction { body, body_bytes: raw_body.to_vec(), + tx_hash, witness_set, - witness_bytes: raw_witness_set.to_vec(), is_valid, auxiliary_data, auxiliary_bytes: Some(raw_auxiliary_data.to_vec()), }) } + pub(crate) fn new_with_original_bytes( + tx_body: TransactionBody, + raw_body: Vec, + tx_witnesses_set: FixedTxWitnessesSet, + is_valid: bool, + auxiliary_data: Option, + raw_auxiliary_data: Option>, + ) -> FixedTransaction { + let tx_hash = TransactionHash::from(blake2b256(&raw_body)); + + FixedTransaction { + body: tx_body, + body_bytes: raw_body, + tx_hash, + witness_set: tx_witnesses_set, + is_valid, + auxiliary_data, + auxiliary_bytes: raw_auxiliary_data, + } + } + pub fn body(&self) -> TransactionBody { self.body.clone() } @@ -74,19 +97,22 @@ impl FixedTransaction { Ok(()) } + /// We do not recommend using this function, since it might lead to script integrity hash. + /// The only purpose of this struct is to sign the transaction from third-party sources. + /// Use `.sign_and_add_vkey_signature` or `.sign_and_add_icarus_bootstrap_signature` or `.sign_and_add_daedalus_bootstrap_signature` instead. + #[deprecated(since = "12.1.0", note = "Use `.sign_and_add_vkey_signature` or `.sign_and_add_icarus_bootstrap_signature` or `.sign_and_add_daedalus_bootstrap_signature` instead.")] pub fn set_witness_set(&mut self, raw_witness_set: &[u8]) -> Result<(), JsError> { - let witness_set = TransactionWitnessSet::from_bytes(raw_witness_set.to_vec())?; + let witness_set = FixedTxWitnessesSet::from_bytes(raw_witness_set.to_vec())?; self.witness_set = witness_set; - self.witness_bytes = raw_witness_set.to_vec(); Ok(()) } pub fn witness_set(&self) -> TransactionWitnessSet { - self.witness_set.clone() + self.witness_set.tx_witnesses_set() } pub fn raw_witness_set(&self) -> Vec { - self.witness_bytes.clone() + self.witness_set.to_bytes() } pub fn set_is_valid(&mut self, valid: bool) { @@ -111,4 +137,22 @@ impl FixedTransaction { pub fn raw_auxiliary_data(&self) -> Option> { self.auxiliary_bytes.clone() } + + pub fn sign_and_add_vkey_signature(&mut self, private_key: &PrivateKey) -> Result<(), JsError> { + let vkey_witness = make_vkey_witness(&self.tx_hash, private_key); + self.witness_set.add_vkey_witness(vkey_witness); + Ok(()) + } + + pub fn sign_and_add_icarus_bootstrap_signature(&mut self, addr: &ByronAddress, private_key: &Bip32PrivateKey) -> Result<(), JsError> { + let bootstrap_witness = make_icarus_bootstrap_witness(&self.tx_hash, addr, private_key); + self.witness_set.add_bootstrap_witness(bootstrap_witness); + Ok(()) + } + + pub fn sign_and_add_daedalus_bootstrap_signature(&mut self, addr: &ByronAddress, private_key: &LegacyDaedalusPrivateKey) -> Result<(), JsError> { + let bootstrap_witness = make_daedalus_bootstrap_witness(&self.tx_hash, addr, private_key); + self.witness_set.add_bootstrap_witness(bootstrap_witness); + Ok(()) + } } diff --git a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs new file mode 100644 index 00000000..2717ead0 --- /dev/null +++ b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs @@ -0,0 +1,35 @@ +use crate::*; +#[allow(dead_code)] + +pub(crate) struct FixedTxWitnessesSet { + pub(crate) raw_parts: TransactionWitnessSetRaw, + pub(crate) tx_witnesses_set: TransactionWitnessSet, +} + +to_from_bytes!(FixedTxWitnessesSet); + +impl FixedTxWitnessesSet { + pub(crate) fn tx_witnesses_set(&self) -> TransactionWitnessSet { + self.tx_witnesses_set.clone() + } + + pub(crate) fn add_vkey_witness(&mut self, vkey_witness: Vkeywitness) { + if self.tx_witnesses_set.vkeys.is_none() { + self.tx_witnesses_set.vkeys = Some(Vkeywitnesses::new()); + } + if let Some(vkeys) = &mut self.tx_witnesses_set.vkeys { + vkeys.add(&vkey_witness); + } + self.raw_parts.vkeys = None; + } + + pub(crate) fn add_bootstrap_witness(&mut self, bootstrap_witness: BootstrapWitness) { + if self.tx_witnesses_set.bootstraps.is_none() { + self.tx_witnesses_set.bootstraps = Some(BootstrapWitnesses::new()); + } + if let Some(bootstraps) = &mut self.tx_witnesses_set.bootstraps { + bootstraps.add(&bootstrap_witness); + } + self.raw_parts.bootstraps = None; + } +} \ No newline at end of file diff --git a/rust/src/protocol_types/witnesses/mod.rs b/rust/src/protocol_types/witnesses/mod.rs index 5cfd8133..189a7bba 100644 --- a/rust/src/protocol_types/witnesses/mod.rs +++ b/rust/src/protocol_types/witnesses/mod.rs @@ -15,5 +15,9 @@ mod transaction_witnesses_set; pub use transaction_witnesses_set::*; mod transaction_witnesses_sets; + pub use transaction_witnesses_sets::*; +mod fixed_tx_witnesses_set; +pub(crate) use fixed_tx_witnesses_set::*; + diff --git a/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs b/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs index 33c0bef2..a3bd59b7 100644 --- a/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs +++ b/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs @@ -1,6 +1,32 @@ use crate::*; use crate::traits::EmptyToNone; +pub(crate) struct TransactionWitnessSetRaw { + pub(crate) vkeys: Option>, + pub(crate) native_scripts: Option>, + pub(crate) bootstraps: Option>, + pub(crate) plutus_scripts_v1: Option>, + pub(crate) plutus_scripts_v2: Option>, + pub(crate) plutus_scripts_v3: Option>, + pub(crate) plutus_data: Option>, + pub(crate) redeemers: Option>, +} + +impl TransactionWitnessSetRaw { + pub(crate) fn new() -> Self { + Self { + vkeys: None, + native_scripts: None, + bootstraps: None, + plutus_scripts_v1: None, + plutus_scripts_v2: None, + plutus_scripts_v3: None, + plutus_data: None, + redeemers: None, + } + } +} + #[wasm_bindgen] #[derive(Clone, Eq, PartialEq, Debug, serde::Serialize, serde::Deserialize, JsonSchema)] pub struct TransactionWitnessSet { diff --git a/rust/src/serialization/fixed_tx.rs b/rust/src/serialization/fixed_tx.rs index c4b5f58c..ca5153c0 100644 --- a/rust/src/serialization/fixed_tx.rs +++ b/rust/src/serialization/fixed_tx.rs @@ -8,7 +8,7 @@ impl cbor_event::se::Serialize for FixedTransaction { ) -> cbor_event::Result<&'se mut Serializer> { serializer.write_array(cbor_event::Len::Len(4))?; serializer.write_raw_bytes(&self.body_bytes)?; - serializer.write_raw_bytes(&self.witness_bytes)?; + self.witness_set.serialize(serializer)?; serializer.write_special(CBORSpecial::Bool(self.is_valid))?; match &self.auxiliary_bytes { Some(auxiliary_bytes) => serializer.write_raw_bytes(auxiliary_bytes)?, @@ -52,9 +52,8 @@ impl DeserializeEmbeddedGroup for FixedTransaction { let (body, body_bytes) = deserilized_with_orig_bytes(raw, |raw| TransactionBody::deserialize(raw)) .map_err(|e| e.annotate("body"))?; - let (witness_set, witness_bytes) = - deserilized_with_orig_bytes(raw, |raw| TransactionWitnessSet::deserialize(raw)) - .map_err(|e| e.annotate("witness_set"))?; + let witness_set = FixedTxWitnessesSet::deserialize(raw) + .map_err(|e| e.annotate("witness_set"))?; let mut checked_auxiliary_data = false; let mut auxiliary_data = None; let mut auxiliary_bytes = None; @@ -106,14 +105,13 @@ impl DeserializeEmbeddedGroup for FixedTransaction { })() .map_err(|e| e.annotate("auxiliary_data"))?; } - Ok(FixedTransaction { + Ok(FixedTransaction::new_with_original_bytes( body, body_bytes, witness_set, - witness_bytes, is_valid, auxiliary_data, auxiliary_bytes, - }) + )) } } diff --git a/rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs b/rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs new file mode 100644 index 00000000..b67f086b --- /dev/null +++ b/rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs @@ -0,0 +1,25 @@ +use std::io::{BufRead, Seek, Write}; +use cbor_event::de::Deserializer; +use cbor_event::se::Serializer; +use crate::protocol_types::{Deserialize, FixedTxWitnessesSet}; +use crate::{DeserializeError}; + +impl cbor_event::se::Serialize for FixedTxWitnessesSet { + fn serialize<'a, W: Write + Sized>(&self, serializer: &'a mut Serializer) -> cbor_event::Result<&'a mut Serializer> { + super::transaction_witnesses_set::serialize(&self.tx_witnesses_set, Some(&self.raw_parts), serializer) + } +} + +impl Deserialize for FixedTxWitnessesSet { + fn deserialize(raw: &mut Deserializer) -> Result + where + Self: Sized + { + let (witness_set, raw_parts) = super::transaction_witnesses_set::deserialize(raw, false)?; + Ok(Self { + tx_witnesses_set: witness_set, + raw_parts + }) + } +} + diff --git a/rust/src/serialization/witnesses/mod.rs b/rust/src/serialization/witnesses/mod.rs index f23c6da7..7dca7c85 100644 --- a/rust/src/serialization/witnesses/mod.rs +++ b/rust/src/serialization/witnesses/mod.rs @@ -3,4 +3,5 @@ mod vkeywitnesses; mod bootstrap_witness; mod bootstrap_witnesses; mod transaction_witnesses_set; -mod transaction_witnesses_sets; \ No newline at end of file +mod transaction_witnesses_sets; +mod fixed_tx_witnesses_set; \ No newline at end of file diff --git a/rust/src/serialization/witnesses/transaction_witnesses_set.rs b/rust/src/serialization/witnesses/transaction_witnesses_set.rs index 578fa179..6967f09e 100644 --- a/rust/src/serialization/witnesses/transaction_witnesses_set.rs +++ b/rust/src/serialization/witnesses/transaction_witnesses_set.rs @@ -1,249 +1,304 @@ use std::io::{BufRead, Seek, Write}; use cbor_event::de::Deserializer; use cbor_event::se::Serializer; +use cbor_event::Serialize; use crate::{BootstrapWitnesses, CBORReadLen, DeserializeError, DeserializeFailure, Key, Language, NativeScripts, PlutusList, PlutusScripts, Redeemers, TransactionWitnessSet, Vkeywitnesses}; -use crate::protocol_types::{CBORSpecial, CBORType, Deserialize, opt64}; -use crate::serialization::utils::merge_option_plutus_list; +use crate::protocol_types::{CBORSpecial, CBORType, Deserialize, opt64, TransactionWitnessSetRaw}; +use crate::serialization::utils::{deserilized_with_orig_bytes, merge_option_plutus_list}; use crate::traits::NoneOrEmpty; use crate::utils::opt64_non_empty; impl cbor_event::se::Serialize for TransactionWitnessSet { - fn serialize<'se, W: Write>( - &self, - serializer: &'se mut Serializer, - ) -> cbor_event::Result<&'se mut Serializer> { - let mut has_plutus_v1 = false; - let mut has_plutus_v2 = false; - let mut has_plutus_v3 = false; - let plutus_added_length = match &self.plutus_scripts { - Some(scripts) => { - has_plutus_v1 = scripts.has_version(&Language::new_plutus_v1()); - has_plutus_v2 = scripts.has_version(&Language::new_plutus_v2()); - has_plutus_v3 = scripts.has_version(&Language::new_plutus_v3()); - (has_plutus_v1 as u64) + (has_plutus_v2 as u64) + (has_plutus_v3 as u64) - }, - _ => 0, - }; - serializer.write_map(cbor_event::Len::Len( - opt64(&self.vkeys) - + opt64_non_empty(&self.native_scripts) - + opt64_non_empty(&self.bootstraps) - + opt64_non_empty(&self.plutus_data) - + opt64_non_empty(&self.redeemers) - + plutus_added_length, - ))?; - if let Some(field) = &self.vkeys { - if !field.is_none_or_empty() { - serializer.write_unsigned_integer(0)?; - field.serialize(serializer)?; + fn serialize<'a, W: Write + Sized>(&self, serializer: &'a mut Serializer) -> cbor_event::Result<&'a mut Serializer> { + serialize(self, None, serializer) + } +} + +impl Deserialize for TransactionWitnessSet { + fn deserialize(raw: &mut Deserializer) -> Result + where + Self: Sized + { + let (witness_set, _) = deserialize(raw, false)?; + Ok(witness_set) + } +} + +pub(super) fn deserialize(raw: &mut Deserializer, with_raw_parts: bool) -> Result<(TransactionWitnessSet, TransactionWitnessSetRaw), DeserializeError> { + (|| -> Result<_, DeserializeError> { + let len = raw.map()?; + let mut read_len = CBORReadLen::new(len); + let mut vkeys = None; + let mut native_scripts = None; + let mut bootstraps = None; + let mut plutus_scripts_v1 = None; + let mut plutus_scripts_v2 = None; + let mut plutus_scripts_v3 = None; + let mut plutus_data = None; + let mut redeemers = None; + let mut read = 0; + let mut raw_part = TransactionWitnessSetRaw::new(); + + while match len { + cbor_event::Len::Len(n) => read < n as usize, + cbor_event::Len::Indefinite => true, + } { + match raw.cbor_type()? { + CBORType::UnsignedInteger => match raw.unsigned_integer()? { + 0 => { + if vkeys.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into()); + } + read_len.read_elems(1)?; + let (vkeys_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + Vkeywitnesses::deserialize(raw) + ).map_err(|e| e.annotate("vkeys"))?; + + vkeys = Some(vkeys_deser); + if with_raw_parts { + raw_part.vkeys = Some(raw); + } + } + 1 => { + if native_scripts.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(1)).into()); + } + read_len.read_elems(1)?; + let (native_scripts_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + NativeScripts::deserialize(raw) + ).map_err(|e| e.annotate("native_scripts"))?; + native_scripts = Some(native_scripts_deser); + if with_raw_parts { + raw_part.native_scripts = Some(raw); + } + } + 2 => { + if bootstraps.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into()); + } + read_len.read_elems(1)?; + let (bootstraps_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + BootstrapWitnesses::deserialize(raw) + ).map_err(|e| e.annotate("bootstraps"))?; + bootstraps = Some(bootstraps_deser); + if with_raw_parts { + raw_part.bootstraps = Some(raw); + } + } + 3 => { + if plutus_scripts_v1.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(3)).into()); + } + read_len.read_elems(1)?; + let (plutus_scripts_v1_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v1()) + ).map_err(|e| e.annotate("plutus_scripts_v1"))?; + plutus_scripts_v1 = Some(plutus_scripts_v1_deser); + if with_raw_parts { + raw_part.plutus_scripts_v1 = Some(raw); + } + } + 4 => { + if plutus_data.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(4)).into()); + } + read_len.read_elems(1)?; + let (plutus_data_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + PlutusList::deserialize(raw) + ).map_err(|e| e.annotate("plutus_data"))?; + plutus_data = Some(plutus_data_deser); + if with_raw_parts { + raw_part.plutus_data = Some(raw); + } + } + 5 => { + if redeemers.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(5)).into()); + } + read_len.read_elems(1)?; + let (redeemers_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + Redeemers::deserialize(raw) + ).map_err(|e| e.annotate("redeemers"))?; + redeemers = Some(redeemers_deser); + if with_raw_parts { + raw_part.redeemers = Some(raw); + } + } + 6 => { + if plutus_scripts_v2.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(6)).into()); + } + read_len.read_elems(1)?; + let (plutus_scripts_v2_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v2()) + ).map_err(|e| e.annotate("plutus_scripts_v2"))?; + plutus_scripts_v2 = Some(plutus_scripts_v2_deser); + if with_raw_parts { + raw_part.plutus_scripts_v2 = Some(raw); + } + } + 7 => { + if plutus_scripts_v3.is_some() { + return Err(DeserializeFailure::DuplicateKey(Key::Uint(7)).into()); + } + read_len.read_elems(1)?; + let (plutus_scripts_v3_deser, raw) = deserilized_with_orig_bytes(raw, |raw| + PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v3()) + ).map_err(|e| e.annotate("plutus_scripts_v3"))?; + plutus_scripts_v3 = Some(plutus_scripts_v3_deser); + if with_raw_parts { + raw_part.plutus_scripts_v3 = Some(raw); + } + } + unknown_key => { + return Err( + DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into() + ) + } + }, + CBORType::Text => match raw.text()?.as_str() { + unknown_key => { + return Err(DeserializeFailure::UnknownKey(Key::Str( + unknown_key.to_owned(), + )) + .into()) + } + }, + CBORType::Special => match len { + cbor_event::Len::Len(_) => { + return Err(DeserializeFailure::BreakInDefiniteLen.into()) + } + cbor_event::Len::Indefinite => match raw.special()? { + CBORSpecial::Break => break, + _ => return Err(DeserializeFailure::EndingBreakMissing.into()), + }, + }, + other_type => { + return Err(DeserializeFailure::UnexpectedKeyType(other_type).into()) + } } + read += 1; } - if let Some(field) = &self.native_scripts { - if !field.is_none_or_empty() { - serializer.write_unsigned_integer(1)?; - //transaction witness set already has deduplicated native scripts - field.serialize_as_set(false, serializer)?; - } + read_len.finish()?; + let mut plutus_scripts = None; + plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v1); + plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v2); + plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v3); + + Ok((TransactionWitnessSet { + vkeys, + native_scripts, + bootstraps, + plutus_scripts, + plutus_data, + redeemers, + }, raw_part)) + })() + .map_err(|e| e.annotate("TransactionWitnessSet")) +} + +pub(super) fn serialize<'se, W: Write>( + wit_set: &TransactionWitnessSet, + raw_parts: Option<&TransactionWitnessSetRaw>, + serializer: &'se mut Serializer, +) -> cbor_event::Result<&'se mut Serializer> { + let mut has_plutus_v1 = false; + let mut has_plutus_v2 = false; + let mut has_plutus_v3 = false; + let plutus_added_length = match &wit_set.plutus_scripts { + Some(scripts) => { + has_plutus_v1 = scripts.has_version(&Language::new_plutus_v1()); + has_plutus_v2 = scripts.has_version(&Language::new_plutus_v2()); + has_plutus_v3 = scripts.has_version(&Language::new_plutus_v3()); + (has_plutus_v1 as u64) + (has_plutus_v2 as u64) + (has_plutus_v3 as u64) + }, + _ => 0, + }; + serializer.write_map(cbor_event::Len::Len( + opt64(&wit_set.vkeys) + + opt64_non_empty(&wit_set.native_scripts) + + opt64_non_empty(&wit_set.bootstraps) + + opt64_non_empty(&wit_set.plutus_data) + + opt64_non_empty(&wit_set.redeemers) + + plutus_added_length, + ))?; + if let Some(field) = &wit_set.vkeys { + if let Some(raw_vkeys) = raw_parts.map(|x| x.vkeys.as_ref()).flatten() { + serializer.write_unsigned_integer(0)?; + serializer.write_bytes(raw_vkeys)?; + } else if !field.is_none_or_empty() { + serializer.write_unsigned_integer(0)?; + field.serialize(serializer)?; } - if let Some(field) = &self.bootstraps { - if !field.is_none_or_empty() { - serializer.write_unsigned_integer(2)?; - field.serialize(serializer)?; - } + } + if let Some(field) = &wit_set.native_scripts { + if let Some(raw) = raw_parts.as_ref().map(|x| x.native_scripts.as_ref()).flatten() { + serializer.write_unsigned_integer(1)?; + serializer.write_bytes(raw)?; + } else if !field.is_none_or_empty() { + serializer.write_unsigned_integer(1)?; + //transaction witness set already has deduplicated native scripts + field.serialize_as_set(false, serializer)?; + } + } + if let Some(field) = &wit_set.bootstraps { + if let Some(raw) = raw_parts.as_ref().map(|x| x.bootstraps.as_ref()).flatten() { + serializer.write_unsigned_integer(2)?; + serializer.write_bytes(raw)?; + } else if !field.is_none_or_empty() { + serializer.write_unsigned_integer(2)?; + 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 { + //no need deduplication here because transaction witness set already has deduplicated plutus scripts + if let Some(plutus_scripts) = &wit_set.plutus_scripts { + if has_plutus_v1 { + if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v1.as_ref()).flatten() { + serializer.write_unsigned_integer(3)?; + serializer.write_bytes(raw)?; + } else { serializer.write_unsigned_integer(3)?; plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v1(), serializer)?; } - if has_plutus_v2 { + } + if has_plutus_v2 { + if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v2.as_ref()).flatten() { + serializer.write_unsigned_integer(6)?; + serializer.write_bytes(raw)?; + } else { serializer.write_unsigned_integer(6)?; plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v2(), serializer)?; } - if has_plutus_v3 { + } + if has_plutus_v3 { + if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v3.as_ref()).flatten() { + serializer.write_unsigned_integer(7)?; + serializer.write_bytes(raw)?; + } else { serializer.write_unsigned_integer(7)?; plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v3(), serializer)?; } } - if let Some(field) = &self.plutus_data { - if !field.is_none_or_empty() { - serializer.write_unsigned_integer(4)?; - //transaction witness set already has deduplicated plutus data - field.serialize_as_set(false, serializer)?; - } + } + if let Some(field) = &wit_set.plutus_data { + if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_data.as_ref()).flatten() { + serializer.write_unsigned_integer(4)?; + serializer.write_bytes(&raw)?; + } else if !field.is_none_or_empty() { + serializer.write_unsigned_integer(4)?; + //transaction witness set already has deduplicated plutus data + field.serialize_as_set(false, serializer)?; } - if let Some(field) = &self.redeemers { - if !field.is_none_or_empty() { - serializer.write_unsigned_integer(5)?; - field.serialize(serializer)?; - } + } + if let Some(field) = &wit_set.redeemers { + if let Some(raw) = raw_parts.as_ref().map(|x| x.redeemers.as_ref()).flatten() { + serializer.write_unsigned_integer(5)?; + serializer.write_bytes(raw)?; + } else if !field.is_none_or_empty() { + serializer.write_unsigned_integer(5)?; + field.serialize(serializer)?; } - Ok(serializer) } + Ok(serializer) } - -impl Deserialize for TransactionWitnessSet { - fn deserialize(raw: &mut Deserializer) -> Result { - (|| -> Result<_, DeserializeError> { - let len = raw.map()?; - let mut read_len = CBORReadLen::new(len); - let mut vkeys = None; - let mut native_scripts = None; - let mut bootstraps = None; - let mut plutus_scripts_v1 = None; - let mut plutus_scripts_v2 = None; - let mut plutus_scripts_v3 = None; - let mut plutus_data = None; - let mut redeemers = None; - let mut read = 0; - while match len { - cbor_event::Len::Len(n) => read < n as usize, - cbor_event::Len::Indefinite => true, - } { - match raw.cbor_type()? { - CBORType::UnsignedInteger => match raw.unsigned_integer()? { - 0 => { - if vkeys.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(0)).into()); - } - vkeys = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(Vkeywitnesses::deserialize(raw)?) - })() - .map_err(|e| e.annotate("vkeys"))?, - ); - } - 1 => { - if native_scripts.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(1)).into()); - } - native_scripts = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(NativeScripts::deserialize(raw)?) - })() - .map_err(|e| e.annotate("native_scripts"))?, - ); - } - 2 => { - if bootstraps.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(2)).into()); - } - bootstraps = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(BootstrapWitnesses::deserialize(raw)?) - })() - .map_err(|e| e.annotate("bootstraps"))?, - ); - } - 3 => { - if plutus_scripts_v1.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(3)).into()); - } - plutus_scripts_v1 = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(PlutusScripts::deserialize(raw)?) - })() - .map_err(|e| e.annotate("plutus_scripts_v1"))?, - ); - } - 4 => { - if plutus_data.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(4)).into()); - } - plutus_data = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(PlutusList::deserialize(raw)?) - })() - .map_err(|e| e.annotate("plutus_data"))?, - ); - } - 5 => { - if redeemers.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(5)).into()); - } - redeemers = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(Redeemers::deserialize(raw)?) - })() - .map_err(|e| e.annotate("redeemers"))?, - ); - } - 6 => { - if plutus_scripts_v2.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(6)).into()); - } - plutus_scripts_v2 = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v2())?) - })() - .map_err(|e| e.annotate("plutus_scripts_v2"))?, - ); - } - 7 => { - if plutus_scripts_v3.is_some() { - return Err(DeserializeFailure::DuplicateKey(Key::Uint(7)).into()); - } - plutus_scripts_v3 = Some( - (|| -> Result<_, DeserializeError> { - read_len.read_elems(1)?; - Ok(PlutusScripts::deserialize_with_version(raw, &Language::new_plutus_v3())?) - })() - .map_err(|e| e.annotate("plutus_scripts_v3"))?, - ); - } - unknown_key => { - return Err( - DeserializeFailure::UnknownKey(Key::Uint(unknown_key)).into() - ) - } - }, - CBORType::Text => match raw.text()?.as_str() { - unknown_key => { - return Err(DeserializeFailure::UnknownKey(Key::Str( - unknown_key.to_owned(), - )) - .into()) - } - }, - CBORType::Special => match len { - cbor_event::Len::Len(_) => { - return Err(DeserializeFailure::BreakInDefiniteLen.into()) - } - cbor_event::Len::Indefinite => match raw.special()? { - CBORSpecial::Break => break, - _ => return Err(DeserializeFailure::EndingBreakMissing.into()), - }, - }, - other_type => { - return Err(DeserializeFailure::UnexpectedKeyType(other_type).into()) - } - } - read += 1; - } - read_len.finish()?; - let mut plutus_scripts = None; - plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v1); - plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v2); - plutus_scripts = merge_option_plutus_list(plutus_scripts, plutus_scripts_v3); - - Ok(Self { - vkeys, - native_scripts, - bootstraps, - plutus_scripts, - plutus_data, - redeemers, - }) - })() - .map_err(|e| e.annotate("TransactionWitnessSet")) - } -} \ No newline at end of file diff --git a/rust/src/tests/protocol_types/fixed_tx.rs b/rust/src/tests/protocol_types/fixed_tx.rs index cb9b09e0..84edc34d 100644 --- a/rust/src/tests/protocol_types/fixed_tx.rs +++ b/rust/src/tests/protocol_types/fixed_tx.rs @@ -9,8 +9,11 @@ fn simple_round_trip() { let tx = FixedTransaction::new(&body, &wit_set, true).unwrap(); let tx2 = FixedTransaction::from_bytes(tx.to_bytes()).unwrap(); + let wit_set_decoded = TransactionWitnessSet::from_bytes(wit_set).unwrap(); + let wit_set_decoded_2 = TransactionWitnessSet::from_bytes(tx2.raw_witness_set()).unwrap(); + assert_eq!(body, tx2.raw_body()); - assert_eq!(wit_set, tx2.raw_witness_set()); + assert_eq!(wit_set_decoded, wit_set_decoded_2); assert_eq!(tx.raw_body(), tx2.raw_body()); assert_eq!(tx.raw_witness_set(), tx2.raw_witness_set()); assert_eq!(tx.is_valid(), tx2.is_valid()); @@ -45,12 +48,15 @@ fn round_trip_nonstandart_body() { let tx2 = Transaction::from_bytes(tx.to_bytes()).unwrap(); let tx3 = FixedTransaction::from_bytes(tx.to_bytes()).unwrap(); + let wit_set_decoded = TransactionWitnessSet::from_bytes(wit_set).unwrap(); + let wit_set_decoded_2 = TransactionWitnessSet::from_bytes(tx3.raw_witness_set()).unwrap(); + assert_eq!(casual_tx.body(), tx.body()); assert_eq!(casual_tx.witness_set(), tx.witness_set()); assert_eq!(casual_tx.is_valid(), tx.is_valid()); assert_eq!(body, tx3.raw_body()); - assert_eq!(wit_set, tx3.raw_witness_set()); + assert_eq!(wit_set_decoded, wit_set_decoded_2); assert_eq!(tx.raw_body(), tx3.raw_body()); assert_eq!(tx.raw_witness_set(), tx3.raw_witness_set()); assert_eq!(tx.is_valid(), tx3.is_valid()); From b8d771cef069e58d15a0582f5bd07ebeba880389 Mon Sep 17 00:00:00 2001 From: lisicky Date: Wed, 4 Sep 2024 04:45:38 +0900 Subject: [PATCH 06/19] Revert "add "set" tag as default for serialization" This reverts commit c7682ab6b863c746fba704caf8d481c879b189d7. --- .../builders/batch_tools/cbor_calculator.rs | 38 +------------------ .../batch_tools/witnesses_calculator.rs | 16 ++++---- .../certificates/certificates_collection.rs | 3 +- rust/src/serialization/credentials.rs | 3 +- rust/src/serialization/ed25519_key_hashes.rs | 3 +- .../governance/proposals/voting_proposals.rs | 3 +- rust/src/serialization/native_scripts.rs | 3 +- rust/src/serialization/plutus/plutus_data.rs | 3 +- .../serialization/plutus/plutus_scripts.rs | 3 +- rust/src/serialization/tx_inputs.rs | 3 +- .../witnesses/bootstrap_witnesses.rs | 3 +- .../serialization/witnesses/vkeywitnesses.rs | 3 +- rust/src/tests/builders/tx_builder.rs | 28 +++++++------- rust/src/tests/fees.rs | 20 +++++----- rust/src/tests/plutus.rs | 10 ++--- rust/src/tests/utils.rs | 4 +- 16 files changed, 61 insertions(+), 85 deletions(-) diff --git a/rust/src/builders/batch_tools/cbor_calculator.rs b/rust/src/builders/batch_tools/cbor_calculator.rs index 83ebc1cd..fec45147 100644 --- a/rust/src/builders/batch_tools/cbor_calculator.rs +++ b/rust/src/builders/batch_tools/cbor_calculator.rs @@ -26,17 +26,6 @@ impl CborCalculator { } } - pub(super) fn get_wrapped_struct_size(items_count: u64) -> usize { - //wrapped struct is a struct of 2 elements, tag and value - let tag_size = CborCalculator::get_tag_size(258); - let value_size = CborCalculator::get_struct_size(items_count); - tag_size + value_size - } - - pub(super) fn get_tag_size(tag: u64) -> usize { - Self::get_struct_size(tag) - } - pub(super) fn get_coin_size(coin: &Coin) -> usize { Self::get_struct_size(coin.clone().into()) } @@ -82,35 +71,12 @@ impl CborCalculator { pub(super) fn get_bare_tx_body_size(body_fields: &HashSet) -> usize { let mut size = CborCalculator::get_struct_size(body_fields.len() as u64); for field in body_fields { - let wrapped = match field { - TxBodyNames::Inputs => true, - TxBodyNames::Outputs => false, - TxBodyNames::Fee => false, - TxBodyNames::Ttl => false, - TxBodyNames::Certs => true, - TxBodyNames::Withdrawals => false, - TxBodyNames::Update => false, - TxBodyNames::AuxiliaryDataHash => false, - TxBodyNames::ValidityStartInterval => false, - TxBodyNames::Mint => false, - TxBodyNames::ScriptDataHash => false, - TxBodyNames::Collateral => true, - TxBodyNames::RequiredSigners => true, - TxBodyNames::NetworkId => false, - TxBodyNames::CollateralReturn => false, - TxBodyNames::TotalCollateral => false, - TxBodyNames::ReferenceInputs => true, - }; - if wrapped { - size += CborCalculator::get_wrapped_struct_size(field.to_u64().unwrap()); - } else { - size += CborCalculator::get_struct_size(field.to_u64().unwrap()); - } + size += CborCalculator::get_struct_size(field.to_u64().unwrap()); } size } - pub(super) fn get_witnesses_set_struct_size( + pub(super) fn get_wintnesses_set_struct_size( witnesses_fields: &HashSet, ) -> usize { let mut size = CborCalculator::get_struct_size(witnesses_fields.len() as u64); diff --git a/rust/src/builders/batch_tools/witnesses_calculator.rs b/rust/src/builders/batch_tools/witnesses_calculator.rs index 62a5a1eb..b0c50614 100644 --- a/rust/src/builders/batch_tools/witnesses_calculator.rs +++ b/rust/src/builders/batch_tools/witnesses_calculator.rs @@ -144,18 +144,18 @@ impl WitnessesCalculator { if self.vkeys_count == 0 { if self.used_fields.len() > 0 { self.total_size -= - CborCalculator::get_witnesses_set_struct_size(&self.used_fields); + CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); } self.used_fields.insert(WitnessSetNames::Vkeys); - self.total_size += CborCalculator::get_witnesses_set_struct_size(&self.used_fields); + self.total_size += CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); } if self.vkeys_count != 0 { - self.total_size -= CborCalculator::get_wrapped_struct_size(self.vkeys_count); + self.total_size -= CborCalculator::get_struct_size(self.vkeys_count); } self.vkeys_count += 1; - self.total_size += CborCalculator::get_wrapped_struct_size(self.vkeys_count); + self.total_size += CborCalculator::get_struct_size(self.vkeys_count); self.total_size += CborCalculator::get_fake_vkey_size(); } @@ -164,18 +164,18 @@ impl WitnessesCalculator { if self.boostrap_count == 0 { if self.used_fields.len() > 0 { self.total_size -= - CborCalculator::get_witnesses_set_struct_size(&self.used_fields); + CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); } self.used_fields.insert(WitnessSetNames::Bootstraps); - self.total_size += CborCalculator::get_witnesses_set_struct_size(&self.used_fields); + self.total_size += CborCalculator::get_wintnesses_set_struct_size(&self.used_fields); } if self.boostrap_count != 0 { - self.total_size -= CborCalculator::get_wrapped_struct_size(self.boostrap_count); + self.total_size -= CborCalculator::get_struct_size(self.boostrap_count); } self.boostrap_count += 1; - self.total_size += CborCalculator::get_wrapped_struct_size(self.boostrap_count); + self.total_size += CborCalculator::get_struct_size(self.boostrap_count); self.total_size += CborCalculator::get_boostrap_witness_size(address); } } diff --git a/rust/src/serialization/certificates/certificates_collection.rs b/rust/src/serialization/certificates/certificates_collection.rs index f4beb222..06b12c7e 100644 --- a/rust/src/serialization/certificates/certificates_collection.rs +++ b/rust/src/serialization/certificates/certificates_collection.rs @@ -6,7 +6,8 @@ impl Serialize for Certificates { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; serializer.write_array(Len::Len(self.len() as u64))?; for element in &self.certs { element.serialize(serializer)?; diff --git a/rust/src/serialization/credentials.rs b/rust/src/serialization/credentials.rs index 5c83a851..a45086fb 100644 --- a/rust/src/serialization/credentials.rs +++ b/rust/src/serialization/credentials.rs @@ -6,7 +6,8 @@ impl cbor_event::se::Serialize for Credentials { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in self.to_vec() { element.serialize(serializer)?; diff --git a/rust/src/serialization/ed25519_key_hashes.rs b/rust/src/serialization/ed25519_key_hashes.rs index 232c4c61..46d6a73e 100644 --- a/rust/src/serialization/ed25519_key_hashes.rs +++ b/rust/src/serialization/ed25519_key_hashes.rs @@ -6,7 +6,8 @@ impl Serialize for Ed25519KeyHashes { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in self.to_vec() { element.serialize(serializer)?; diff --git a/rust/src/serialization/governance/proposals/voting_proposals.rs b/rust/src/serialization/governance/proposals/voting_proposals.rs index 53b967ce..64ee941a 100644 --- a/rust/src/serialization/governance/proposals/voting_proposals.rs +++ b/rust/src/serialization/governance/proposals/voting_proposals.rs @@ -6,7 +6,8 @@ impl cbor_event::se::Serialize for VotingProposals { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in &self.proposals { element.serialize(serializer)?; diff --git a/rust/src/serialization/native_scripts.rs b/rust/src/serialization/native_scripts.rs index 3cf2bdad..8b3f5e7b 100644 --- a/rust/src/serialization/native_scripts.rs +++ b/rust/src/serialization/native_scripts.rs @@ -20,7 +20,8 @@ impl NativeScripts { need_deduplication: bool, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; if need_deduplication { let view = self.deduplicated_view(); serializer.write_array(cbor_event::Len::Len(self.0.len() as u64))?; diff --git a/rust/src/serialization/plutus/plutus_data.rs b/rust/src/serialization/plutus/plutus_data.rs index 6c806cb2..f3ce5f64 100644 --- a/rust/src/serialization/plutus/plutus_data.rs +++ b/rust/src/serialization/plutus/plutus_data.rs @@ -243,7 +243,8 @@ impl PlutusList { need_deduplication: bool, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; let use_definite_encoding = match self.definite_encoding { Some(definite) => definite, None => self.elems.is_empty(), diff --git a/rust/src/serialization/plutus/plutus_scripts.rs b/rust/src/serialization/plutus/plutus_scripts.rs index ab0832b0..37f30906 100644 --- a/rust/src/serialization/plutus/plutus_scripts.rs +++ b/rust/src/serialization/plutus/plutus_scripts.rs @@ -34,7 +34,8 @@ impl PlutusScripts { version: &Language, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; let view = match need_deduplication { true => self.deduplicated_view(Some(version)), false => self.view(version), diff --git a/rust/src/serialization/tx_inputs.rs b/rust/src/serialization/tx_inputs.rs index 7d6e1350..7fcc683d 100644 --- a/rust/src/serialization/tx_inputs.rs +++ b/rust/src/serialization/tx_inputs.rs @@ -6,7 +6,8 @@ impl cbor_event::se::Serialize for TransactionInputs { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.len() as u64))?; for element in &self.inputs { element.serialize(serializer)?; diff --git a/rust/src/serialization/witnesses/bootstrap_witnesses.rs b/rust/src/serialization/witnesses/bootstrap_witnesses.rs index 3f4f7a98..d4d4464c 100644 --- a/rust/src/serialization/witnesses/bootstrap_witnesses.rs +++ b/rust/src/serialization/witnesses/bootstrap_witnesses.rs @@ -10,7 +10,8 @@ impl cbor_event::se::Serialize for BootstrapWitnesses { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.get_vec_wits().len() as u64))?; for element in self.get_vec_wits() { element.serialize(serializer)?; diff --git a/rust/src/serialization/witnesses/vkeywitnesses.rs b/rust/src/serialization/witnesses/vkeywitnesses.rs index ddf4c92a..f3190569 100644 --- a/rust/src/serialization/witnesses/vkeywitnesses.rs +++ b/rust/src/serialization/witnesses/vkeywitnesses.rs @@ -10,7 +10,8 @@ impl cbor_event::se::Serialize for Vkeywitnesses { &self, serializer: &'se mut Serializer, ) -> cbor_event::Result<&'se mut Serializer> { - serializer.write_tag(258)?; + //TODO: uncomment this line when we conway ero will come + //serializer.write_tag(258)?; serializer.write_array(cbor_event::Len::Len(self.witnesses.len() as u64))?; for element in &self.witnesses { element.serialize(serializer)?; diff --git a/rust/src/tests/builders/tx_builder.rs b/rust/src/tests/builders/tx_builder.rs index 1a36c543..22c2b8f4 100644 --- a/rust/src/tests/builders/tx_builder.rs +++ b/rust/src/tests/builders/tx_builder.rs @@ -98,7 +98,7 @@ fn build_tx_with_change() { .checked_add(&Value::new(&tx_builder.get_fee_if_set().unwrap())) .unwrap() ); - assert_eq!(tx_builder.full_size().unwrap(), 291); + assert_eq!(tx_builder.full_size().unwrap(), 285); assert_eq!(tx_builder.output_sizes(), vec![62, 65]); let _final_tx = tx_builder.build(); // just test that it doesn't throw } @@ -172,7 +172,7 @@ fn build_tx_with_change_with_datum() { .checked_add(&Value::new(&tx_builder.get_fee_if_set().unwrap())) .unwrap() ); - assert_eq!(tx_builder.full_size().unwrap(), 325); + assert_eq!(tx_builder.full_size().unwrap(), 319); assert_eq!(tx_builder.output_sizes(), vec![62, 99]); let _final_tx = tx_builder.build(); // just test that it doesn't throw } @@ -304,8 +304,8 @@ fn build_tx_with_certs() { ) .to_address(); tx_builder.add_change_if_needed(&change_addr).unwrap(); - assert_eq!(tx_builder.min_fee().unwrap().to_str(), "218502"); - assert_eq!(tx_builder.get_fee_if_set().unwrap().to_str(), "218502"); + assert_eq!(tx_builder.min_fee().unwrap().to_str(), "214002"); + assert_eq!(tx_builder.get_fee_if_set().unwrap().to_str(), "214002"); assert_eq!(tx_builder.get_deposit().unwrap().to_str(), "1000000"); assert_eq!(tx_builder.outputs.len(), 1); assert_eq!( @@ -559,7 +559,7 @@ fn build_tx_with_inputs() { ) .unwrap() .to_str(), - "71000" + "69500" ); tx_builder.add_regular_input( &EnterpriseAddress::new(NetworkInfo::testnet_preprod().network_id(), &spend_cred) @@ -1592,7 +1592,7 @@ fn build_tx_with_native_assets_change_and_no_purification_cuz_not_enough_pure_co ); // The single change output contains more Coin then minimal utxo value // But not enough to cover the additional fee for a separate output - assert_eq!(final_tx.outputs().get(1).amount().coin(), BigNum(493)); + assert_eq!(final_tx.outputs().get(1).amount().coin(), BigNum(499)); } #[test] @@ -2512,7 +2512,7 @@ fn tx_builder_cip2_random_improve_adds_enough_for_fees() { .unwrap(), ) .unwrap(); - assert_eq!(tx_builder.min_fee().unwrap(), BigNum(56)); + assert_eq!(tx_builder.min_fee().unwrap(), BigNum(53)); let mut available_inputs = TransactionUnspentOutputs::new(); available_inputs.add(&make_input(1u8, Value::new(&BigNum(150)))); available_inputs.add(&make_input(2u8, Value::new(&BigNum(150)))); @@ -2520,7 +2520,7 @@ fn tx_builder_cip2_random_improve_adds_enough_for_fees() { let add_inputs_res = tx_builder.add_inputs_from(&available_inputs, CoinSelectionStrategyCIP2::RandomImprove); assert!(add_inputs_res.is_ok(), "{:?}", add_inputs_res.err()); - assert_eq!(tx_builder.min_fee().unwrap(), BigNum(270)); + assert_eq!(tx_builder.min_fee().unwrap(), BigNum(264)); let change_addr = ByronAddress::from_base58("Ae2tdPwUPEZGUEsuMAhvDcy94LKsZxDjCbgaiBBMgYpR8sKf96xJmit7Eho") .unwrap() @@ -3529,7 +3529,7 @@ fn add_mint_includes_witnesses_into_fee_estimation() { // Original tx fee now assumes two VKey signatures for two inputs let original_tx_fee = tx_builder.min_fee().unwrap(); - assert_eq!(original_tx_fee, BigNum(168625)); + assert_eq!(original_tx_fee, BigNum(168361)); // Add minting four assets from three different policies tx_builder.add_mint_asset(&mint_script1, &name1, &amount).expect("Failed to add mint asset"); @@ -3555,7 +3555,7 @@ fn add_mint_includes_witnesses_into_fee_estimation() { .unwrap(); assert_eq!(raw_mint_fee, BigNum(5544)); - assert_eq!(raw_mint_script_fee, BigNum(4444)); + assert_eq!(raw_mint_script_fee, BigNum(4312)); let new_tx_fee = tx_builder.min_fee().unwrap(); @@ -4364,10 +4364,10 @@ fn test_ex_unit_costs_are_added_to_the_fees() { tx_builder.get_fee_if_set().unwrap() } - assert_eq!(calc_fee_with_ex_units(0, 0), BigNum(174169)); - assert_eq!(calc_fee_with_ex_units(10000, 0), BigNum(174834)); - assert_eq!(calc_fee_with_ex_units(0, 10000000), BigNum(175066)); - assert_eq!(calc_fee_with_ex_units(10000, 10000000), BigNum(175731)); + assert_eq!(calc_fee_with_ex_units(0, 0), BigNum(173509)); + assert_eq!(calc_fee_with_ex_units(10000, 0), BigNum(174174)); + assert_eq!(calc_fee_with_ex_units(0, 10000000), BigNum(174406)); + assert_eq!(calc_fee_with_ex_units(10000, 10000000), BigNum(175071)); } #[test] diff --git a/rust/src/tests/fees.rs b/rust/src/tests/fees.rs index bc19fb6f..04de0d19 100644 --- a/rust/src/tests/fees.rs +++ b/rust/src/tests/fees.rs @@ -55,11 +55,11 @@ fn tx_simple_utxo() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a400d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00016f32030aa100d9010281825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee58406d68d8b7b2ee54f1f46b64e3f61a14f840be2ec125c858ec917f634a1eb898a51660654839226016a2588d39920e6dfe1b66d917027f198b5eb887d20f4ac805f5f6" + "84a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00016f32030aa10081825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee5840fae5de40c94d759ce13bf9886262159c4f26a289fd192e165995b785259e503f6887bf39dfa23a47cf163784c6eee23f61440e749bc1df3c73975f5231aeda0ff5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "97502" // todo: compare to Haskell fee to make sure the diff is not too big + "94502" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -109,11 +109,11 @@ fn tx_simple_byron_utxo() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a400d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a0001b582030aa102d9010281845820473811afd4d939b337c9be1a2ceeb2cb2c75108bddf224c5c21c51592a7b204a58408b4ca7a71340bc6441f0e390122d53aba154b7e2b432ec2927ed8db7395d3d9347989aa1fca4823c991c1ef309570a0bbdf62155e3dba376fae9827cb465f5055820c8b95d0d35fe75a70f9f5633a3e2439b2994b9e2bc851c49e9f91d1a5dcbb1a341a0f5f6" + "84a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a0001b582030aa10281845820473811afd4d939b337c9be1a2ceeb2cb2c75108bddf224c5c21c51592a7b204a5840f0b04a852353eb23b9570df80b2aa6a61b723341ab45a2024a05b07cf58be7bdfbf722c09040db6cee61a0d236870d6ad1e1349ac999ec0db28f9471af25fb0c5820c8b95d0d35fe75a70f9f5633a3e2439b2994b9e2bc851c49e9f91d1a5dcbb1a341a0f5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "115502" // todo: compare to Haskell fee to make sure the diff is not too big + "112502" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -196,11 +196,11 @@ fn tx_multi_utxo() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a400d90102828258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7182a82582082839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace3207018282581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c19012182581d61bcd18fcffa797c16c007014e2b8553b8b9b1e94c507688726243d6111a3420989c021a0002ccce031903e7a100d9010282825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee584082eea9c7848c1136ebcb5fd5774d8dfc330c63b7f44b56a5cc5008887d3923df8785ebab92c230114099cf9b79a6c6c57ead026fa495d526731cc00caa3407088258206872b0a874acfe1cace12b20ea348559a7ecc912f2fc7f674f43481df973d92c5840f8861b68b3f966b6b63cbd3f7abf18efa18620aee9e730dea75d2d1cb0668988486f852f7743f6b5cc841c62d11440073706b52b408c0d776a411e2a0dd0da0af5f6" + "84a400828258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7182a82582082839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace3207018282581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c19012182581d61bcd18fcffa797c16c007014e2b8553b8b9b1e94c507688726243d6111a3420989c021a0002ccce031903e7a10082825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee58401ec3e56008650282ba2e1f8a20e81707810b2d0973c4d42a1b4df65b732bda81567c7824904840b2554d2f33861da5d70588a29d33b2b61042e3c3445301d8008258206872b0a874acfe1cace12b20ea348559a7ecc912f2fc7f674f43481df973d92c5840a0718fb5b37d89ddf926c08e456d3f4c7f749e91f78bb3e370751d5b632cbd20d38d385805291b1ef2541b02543728a235e01911f4b400bfb50e5fce589de907f5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "187002" // todo: compare to Haskell fee to make sure the diff is not too big + "184002" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -317,11 +317,11 @@ fn tx_register_stake() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a500d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00040f12030a04d90102818a03581c1c13374874c68016df54b1339b6cacdd801098431e7659b24928efc15820bd0000f498ccacdc917c28274cba51c415f3f21931ff41ca8dc1197499f8e1241a000f42401a000f4240d81e82031864581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af70d9010281581c51df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af7080f6a100d9010283825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee584081e223791960a07f401c378dce048ea658a155510ae6541c6cb692ed41ee45b40b913d1428a94af145885639f8acf99549f7b29af1e34997b9cb8ad05fe6e50a825820b24c040e65994bd5b0621a060166d32d356ef4be3cc1f848426a4cf38688708958401a246b6a4d63e83bd4904ac3b787797ba54238aab8e733b75b5ab2e465c46fce67e4403169a53239e7036f87f0518ec4414a10e45a1aa1788322d2777f59c30182582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840ea9518346e8515aea6c16e7076a1d0a637582f736c0b65abd1f4adccd8920f2da699e8602029cc608da2ba46b6a6e61f41166b12ae17c922114c040facd90b07f5f6" + "84a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00040f12030a04818a03581c1c13374874c68016df54b1339b6cacdd801098431e7659b24928efc15820bd0000f498ccacdc917c28274cba51c415f3f21931ff41ca8dc1197499f8e1241a000f42401a000f4240d81e82031864581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af7081581c51df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af7080f6a10083825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee5840a7f305d7e46abfe0f7bea6098bdf853ab9ce8e7aa381be5a991a871852f895a718e20614e22be43494c4dc3a8c78c56cd44fd38e0e5fff3e2fbd19f70402fc02825820b24c040e65994bd5b0621a060166d32d356ef4be3cc1f848426a4cf386887089584013c372f82f1523484eab273241d66d92e1402507760e279480912aa5f0d88d656d6f25d41e65257f2f38c65ac5c918a6735297741adfc718394994f20a1cfd0082582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840d326b993dfec21b9b3e1bd2f80adadc2cd673a1d8d033618cc413b0b02bc3b7efbb23d1ff99138abd05c398ce98e7983a641b50dcf0f64ed33f26c6e636b0b0ff5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "275502" // todo: compare to Haskell fee to make sure the diff is not too big + "269502" // todo: compare to Haskell fee to make sure the diff is not too big ); } @@ -529,11 +529,11 @@ fn tx_withdrawal() { let linear_fee = LinearFee::new(&BigNum(500), &BigNum(2)); assert_eq!( hex::encode(signed_tx.to_bytes()), - "84a500d90102818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00027ac6030a05a1581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af70190539a100d9010282825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee58406dda4d88a17c7b888d15eb29f0871e85f3c50e1ea4efcc0d7781f4db0ae11dd418abae42f7f62637cc54d21887ccb60dc3ccae545e7a25c7c553b3a91e9e6d0082582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840a24b4863189d5872fdb98529bbe6feae375031162786bda1244d73c54adafea0ace2f087f23a794af4f232651ba66071246ab5bc1e1b0b9a39044d0531eeac0ef5f6" + "84a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d611c616f1acb460668a9b2f123c80372c2adad3583b9c6cd2b1deeed1c01021a00027ac6030a05a1581de151df9ba1b74a1c9608a487e114184556801e927d31d96425cb80af70190539a10082825820f9aa3fccb7fe539e471188ccc9ee65514c5961c070b06ca185962484a4813bee5840fc0493f7121efe385d72830680e735ccdef99c3a31953fe877b89ad3a97fcdb871cc7f2cdd6a8104e52f6963bd9e10d814d4fabdbcdc8475bc63e872dcc94d0a82582054d1a9c5ad69586ceeb839c438400c376c0bd34825fb4c17cc2f58c54e1437f35840a051ba927582004aedab736b9f1f9330ff867c260f4751135d480074256e83cd23d2a4bb109f955c43afdcdc5d1841b28d5c1ea2148dfbb6252693590692bb00f5f6" ); assert_eq!( min_fee(&signed_tx, &linear_fee).unwrap().to_str(), - "166002" // todo: compare to Haskell fee to make sure the diff is not too big + "163002" // todo: compare to Haskell fee to make sure the diff is not too big ); } diff --git a/rust/src/tests/plutus.rs b/rust/src/tests/plutus.rs index ac57c7f2..05177e63 100644 --- a/rust/src/tests/plutus.rs +++ b/rust/src/tests/plutus.rs @@ -40,13 +40,13 @@ pub fn plutus_list_serialization_cli_compatibility() { // witness_set should have fixed length array let mut witness_set = TransactionWitnessSet::new(); witness_set.set_plutus_data(&list); - assert_eq!("a104d901029f01ff", hex::encode(witness_set.to_bytes())); + assert_eq!("a1049f01ff", hex::encode(witness_set.to_bytes())); list = PlutusList::new(); list.add(&datum); witness_set.set_plutus_data(&list); assert_eq!( - format!("a104d901029f{}ff", datum_cli), + format!("a1049f{}ff", datum_cli), hex::encode(witness_set.to_bytes()) ); } @@ -436,7 +436,7 @@ fn test_known_plutus_data_hash() { let hash = hash_script_data(&redeemers, &retained_cost_models, Some(pdata)); assert_eq!( hex::encode(hash.to_bytes()), - "296c56ac50bc55b35daa782d11bd35fea58246ce494752bb03a62602aa855a1a" + "2fd8b7e248b376314d02989c885c278796ab0e1d6e8aa0cb91f562ff5f7dbd70" ); } @@ -515,7 +515,7 @@ fn test_known_plutus_data_hash_2() { ); assert_eq!( hex::encode(hash.to_bytes()), - "09bd438e74c7d46bf4e3f29d44220cca441dc11514ab66ba45a9ad7f902b749e" + "0a076247a05aacbecf72ea15b94e3d0331b21295a08d9ab7b8675c13840563a6" ); } @@ -589,6 +589,6 @@ fn script_data_hash_no_redeemers() { ); assert_eq!( hex::encode(hash.to_bytes()), - "fd53a28a846ae6ccf8b221d03d4af122b0b3c442089c05b87e3d86c6792b3ef0" + "5f4e4b313590ed119c077f2ef78ff294118e7955c63982e304a791831238baf4" ); } \ No newline at end of file diff --git a/rust/src/tests/utils.rs b/rust/src/tests/utils.rs index a8c629ca..c8dabac1 100644 --- a/rust/src/tests/utils.rs +++ b/rust/src/tests/utils.rs @@ -459,7 +459,7 @@ fn correct_script_data_hash() { assert_eq!( hex::encode(script_data_hash.to_bytes()), - "1701ce6560526f52bbaa96e49b6f07f3646f3ac2d901b5a38be9a5ee946f7f8a" + "4415e6667e6d6bbd992af5092d48e3c2ba9825200d0234d2470068f7f0f178b3" ); } @@ -733,7 +733,7 @@ fn test_vasil_v1_costmodel_hashing() { ); assert_eq!( hex::encode(hash.to_bytes()), - "c682f77e8adcb58d6db4cd50e342aa452e70c650f67ef35debb1f46327521555" + "887e1b6416d750d871c0f5b7136b54f7b8e8b0e293379d090f38f8f821d08a29" ); } From f2eff15c89e6a53f8c61c5448d0f7a6b94cd6fa2 Mon Sep 17 00:00:00 2001 From: lisicky Date: Wed, 4 Sep 2024 06:10:42 +0900 Subject: [PATCH 07/19] no public wasm to/from bytes --- .../witnesses/fixed_tx_witnesses_set.rs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs index 2717ead0..ab71b841 100644 --- a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs +++ b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs @@ -6,8 +6,6 @@ pub(crate) struct FixedTxWitnessesSet { pub(crate) tx_witnesses_set: TransactionWitnessSet, } -to_from_bytes!(FixedTxWitnessesSet); - impl FixedTxWitnessesSet { pub(crate) fn tx_witnesses_set(&self) -> TransactionWitnessSet { self.tx_witnesses_set.clone() @@ -32,4 +30,22 @@ impl FixedTxWitnessesSet { } self.raw_parts.bootstraps = None; } + + pub(crate) fn to_bytes(&self) -> Vec { + let mut buf = Serializer::new_vec(); + self.serialize(&mut buf).unwrap(); + buf.finalize() + } + + #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))] + pub(crate) fn from_bytes(data: Vec) -> Result { + let mut raw = Deserializer::from(std::io::Cursor::new(data)); + Self::deserialize(&mut raw) + } + + #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] + pub(crate) fn from_bytes(data: Vec) -> Result { + let mut raw = Deserializer::from(std::io::Cursor::new(data)); + Ok(Self::deserialize(&mut raw)?) + } } \ No newline at end of file From ec74c31ece9af861b542c567d261bf9ea61cb665 Mon Sep 17 00:00:00 2001 From: lisicky Date: Wed, 4 Sep 2024 06:10:49 +0900 Subject: [PATCH 08/19] fix flow --- rust/pkg/cardano_serialization_lib.js.flow | 436 +++++++++++---------- 1 file changed, 231 insertions(+), 205 deletions(-) diff --git a/rust/pkg/cardano_serialization_lib.js.flow b/rust/pkg/cardano_serialization_lib.js.flow index b8eedc25..7db77f09 100644 --- a/rust/pkg/cardano_serialization_lib.js.flow +++ b/rust/pkg/cardano_serialization_lib.js.flow @@ -5,6 +5,94 @@ * @flow */ +/** + * @param {string} password + * @param {string} salt + * @param {string} nonce + * @param {string} data + * @returns {string} + */ +declare export function encrypt_with_password( + password: string, + salt: string, + nonce: string, + data: string +): string; + +/** + * @param {string} password + * @param {string} data + * @returns {string} + */ +declare export function decrypt_with_password( + password: string, + data: string +): string; + +/** + * @param {string} json + * @param {$Values< + typeof + PlutusDatumSchema>} schema + * @returns {PlutusData} + */ +declare export function encode_json_str_to_plutus_datum( + json: string, + schema: $Values +): PlutusData; + +/** + * @param {PlutusData} datum + * @param {$Values< + typeof + PlutusDatumSchema>} schema + * @returns {string} + */ +declare export function decode_plutus_datum_to_json_str( + datum: PlutusData, + schema: $Values +): string; + +/** + * @param {Uint8Array} bytes + * @returns {TransactionMetadatum} + */ +declare export function encode_arbitrary_bytes_as_metadatum( + bytes: Uint8Array +): TransactionMetadatum; + +/** + * @param {TransactionMetadatum} metadata + * @returns {Uint8Array} + */ +declare export function decode_arbitrary_bytes_from_metadatum( + metadata: TransactionMetadatum +): Uint8Array; + +/** + * @param {string} json + * @param {$Values< + typeof + MetadataJsonSchema>} schema + * @returns {TransactionMetadatum} + */ +declare export function encode_json_str_to_metadatum( + json: string, + schema: $Values +): TransactionMetadatum; + +/** + * @param {TransactionMetadatum} metadatum + * @param {$Values< + typeof + MetadataJsonSchema>} schema + * @returns {string} + */ +declare export function decode_metadatum_to_json_str( + metadatum: TransactionMetadatum, + schema: $Values +): string; + /** * @param {Address} address * @param {TransactionUnspentOutputs} utxos @@ -142,30 +230,6 @@ declare export function encode_json_str_to_native_script( schema: $Values ): NativeScript; -/** - * @param {string} password - * @param {string} salt - * @param {string} nonce - * @param {string} data - * @returns {string} - */ -declare export function encrypt_with_password( - password: string, - salt: string, - nonce: string, - data: string -): string; - -/** - * @param {string} password - * @param {string} data - * @returns {string} - */ -declare export function decrypt_with_password( - password: string, - data: string -): string; - /** * @param {Transaction} tx * @param {LinearFee} linear_fee @@ -204,129 +268,57 @@ declare export function min_ref_script_fee( ): BigNum; /** - * @param {string} json - * @param {$Values< - typeof - PlutusDatumSchema>} schema - * @returns {PlutusData} */ -declare export function encode_json_str_to_plutus_datum( - json: string, - schema: $Values -): PlutusData; - -/** - * @param {PlutusData} datum - * @param {$Values< - typeof - PlutusDatumSchema>} schema - * @returns {string} - */ -declare export function decode_plutus_datum_to_json_str( - datum: PlutusData, - schema: $Values -): string; -/** - * @param {Uint8Array} bytes - * @returns {TransactionMetadatum} - */ -declare export function encode_arbitrary_bytes_as_metadatum( - bytes: Uint8Array -): TransactionMetadatum; - -/** - * @param {TransactionMetadatum} metadata - * @returns {Uint8Array} - */ -declare export function decode_arbitrary_bytes_from_metadatum( - metadata: TransactionMetadatum -): Uint8Array; - -/** - * @param {string} json - * @param {$Values< - typeof - MetadataJsonSchema>} schema - * @returns {TransactionMetadatum} - */ -declare export function encode_json_str_to_metadatum( - json: string, - schema: $Values -): TransactionMetadatum; - -/** - * @param {TransactionMetadatum} metadatum - * @param {$Values< - typeof - MetadataJsonSchema>} schema - * @returns {string} - */ -declare export function decode_metadatum_to_json_str( - metadatum: TransactionMetadatum, - schema: $Values -): string; - -/** - */ - -declare export var CoinSelectionStrategyCIP2: {| - +LargestFirst: 0, // 0 - +RandomImprove: 1, // 1 - +LargestFirstMultiAsset: 2, // 2 - +RandomImproveMultiAsset: 3, // 3 +declare export var NativeScriptKind: {| + +ScriptPubkey: 0, // 0 + +ScriptAll: 1, // 1 + +ScriptAny: 2, // 2 + +ScriptNOfK: 3, // 3 + +TimelockStart: 4, // 4 + +TimelockExpiry: 5, // 5 |}; /** */ -declare export var CertificateKind: {| - +StakeRegistration: 0, // 0 - +StakeDeregistration: 1, // 1 - +StakeDelegation: 2, // 2 - +PoolRegistration: 3, // 3 - +PoolRetirement: 4, // 4 - +GenesisKeyDelegation: 5, // 5 - +MoveInstantaneousRewardsCert: 6, // 6 - +CommitteeHotAuth: 7, // 7 - +CommitteeColdResign: 8, // 8 - +DRepDeregistration: 9, // 9 - +DRepRegistration: 10, // 10 - +DRepUpdate: 11, // 11 - +StakeAndVoteDelegation: 12, // 12 - +StakeRegistrationAndDelegation: 13, // 13 - +StakeVoteRegistrationAndDelegation: 14, // 14 - +VoteDelegation: 15, // 15 - +VoteRegistrationAndDelegation: 16, // 16 +declare export var BlockEra: {| + +Byron: 0, // 0 + +Shelley: 1, // 1 + +Allegra: 2, // 2 + +Mary: 3, // 3 + +Alonzo: 4, // 4 + +Babbage: 5, // 5 + +Conway: 6, // 6 + +Unknown: 7, // 7 |}; /** */ -declare export var NativeScriptKind: {| - +ScriptPubkey: 0, // 0 - +ScriptAll: 1, // 1 - +ScriptAny: 2, // 2 - +ScriptNOfK: 3, // 3 - +TimelockStart: 4, // 4 - +TimelockExpiry: 5, // 5 +declare export var TransactionMetadatumKind: {| + +MetadataMap: 0, // 0 + +MetadataList: 1, // 1 + +Int: 2, // 2 + +Bytes: 3, // 3 + +Text: 4, // 4 |}; /** */ -declare export var NetworkIdKind: {| - +Testnet: 0, // 0 - +Mainnet: 1, // 1 +declare export var VoteKind: {| + +No: 0, // 0 + +Yes: 1, // 1 + +Abstain: 2, // 2 |}; /** */ -declare export var MetadataJsonSchema: {| - +NoConversions: 0, // 0 - +BasicConversions: 1, // 1 - +DetailedSchema: 2, // 2 +declare export var MIRKind: {| + +ToOtherPot: 0, // 0 + +ToStakeCredentials: 1, // 1 |}; /** @@ -341,15 +333,6 @@ declare export var AddressKind: {| +Malformed: 5, // 5 |}; -/** - */ - -declare export var LanguageKind: {| - +PlutusV1: 0, // 0 - +PlutusV2: 1, // 1 - +PlutusV3: 2, // 2 -|}; - /** */ @@ -366,48 +349,31 @@ declare export var GovernanceActionKind: {| /** */ -declare export var BlockEra: {| - +Byron: 0, // 0 - +Shelley: 1, // 1 - +Allegra: 2, // 2 - +Mary: 3, // 3 - +Alonzo: 4, // 4 - +Babbage: 5, // 5 - +Conway: 6, // 6 - +Unknown: 7, // 7 -|}; - -/** - */ - -declare export var RedeemerTagKind: {| - +Spend: 0, // 0 - +Mint: 1, // 1 - +Cert: 2, // 2 - +Reward: 3, // 3 - +Vote: 4, // 4 - +VotingProposal: 5, // 5 +declare export var MIRPot: {| + +Reserves: 0, // 0 + +Treasury: 1, // 1 |}; /** */ -declare export var DRepKind: {| - +KeyHash: 0, // 0 - +ScriptHash: 1, // 1 - +AlwaysAbstain: 2, // 2 - +AlwaysNoConfidence: 3, // 3 +declare export var NetworkIdKind: {| + +Testnet: 0, // 0 + +Mainnet: 1, // 1 |}; /** + * Each new language uses a different namespace for hashing its script + * This is because you could have a language where the same bytes have different semantics + * So this avoids scripts in different languages mapping to the same hash + * Note that the enum value here is different than the enum value for deciding the cost model of a script */ -declare export var PlutusDataKind: {| - +ConstrPlutusData: 0, // 0 - +Map: 1, // 1 - +List: 2, // 2 - +Integer: 3, // 3 - +Bytes: 4, // 4 +declare export var ScriptHashNamespace: {| + +NativeScript: 0, // 0 + +PlutusScript: 1, // 1 + +PlutusScriptV2: 2, // 2 + +PlutusScriptV3: 3, // 3 |}; /** @@ -430,52 +396,85 @@ declare export var PlutusDatumSchema: {| /** */ -declare export var TransactionMetadatumKind: {| - +MetadataMap: 0, // 0 - +MetadataList: 1, // 1 - +Int: 2, // 2 - +Bytes: 3, // 3 - +Text: 4, // 4 +declare export var CertificateKind: {| + +StakeRegistration: 0, // 0 + +StakeDeregistration: 1, // 1 + +StakeDelegation: 2, // 2 + +PoolRegistration: 3, // 3 + +PoolRetirement: 4, // 4 + +GenesisKeyDelegation: 5, // 5 + +MoveInstantaneousRewardsCert: 6, // 6 + +CommitteeHotAuth: 7, // 7 + +CommitteeColdResign: 8, // 8 + +DRepDeregistration: 9, // 9 + +DRepRegistration: 10, // 10 + +DRepUpdate: 11, // 11 + +StakeAndVoteDelegation: 12, // 12 + +StakeRegistrationAndDelegation: 13, // 13 + +StakeVoteRegistrationAndDelegation: 14, // 14 + +VoteDelegation: 15, // 15 + +VoteRegistrationAndDelegation: 16, // 16 |}; /** - * Each new language uses a different namespace for hashing its script - * This is because you could have a language where the same bytes have different semantics - * So this avoids scripts in different languages mapping to the same hash - * Note that the enum value here is different than the enum value for deciding the cost model of a script */ -declare export var ScriptHashNamespace: {| - +NativeScript: 0, // 0 - +PlutusScript: 1, // 1 - +PlutusScriptV2: 2, // 2 - +PlutusScriptV3: 3, // 3 +declare export var CoinSelectionStrategyCIP2: {| + +LargestFirst: 0, // 0 + +RandomImprove: 1, // 1 + +LargestFirstMultiAsset: 2, // 2 + +RandomImproveMultiAsset: 3, // 3 |}; /** */ -declare export var CredKind: {| - +Key: 0, // 0 - +Script: 1, // 1 +declare export var LanguageKind: {| + +PlutusV1: 0, // 0 + +PlutusV2: 1, // 1 + +PlutusV3: 2, // 2 |}; /** */ -declare export var VoteKind: {| - +No: 0, // 0 - +Yes: 1, // 1 - +Abstain: 2, // 2 +declare export var DRepKind: {| + +KeyHash: 0, // 0 + +ScriptHash: 1, // 1 + +AlwaysAbstain: 2, // 2 + +AlwaysNoConfidence: 3, // 3 |}; /** + * Used to choosed the schema for a script JSON string */ -declare export var RelayKind: {| - +SingleHostAddr: 0, // 0 - +SingleHostName: 1, // 1 - +MultiHostName: 2, // 2 +declare export var ScriptSchema: {| + +Wallet: 0, // 0 + +Node: 1, // 1 +|}; + +/** + */ + +declare export var RedeemerTagKind: {| + +Spend: 0, // 0 + +Mint: 1, // 1 + +Cert: 2, // 2 + +Reward: 3, // 3 + +Vote: 4, // 4 + +VotingProposal: 5, // 5 +|}; + +/** + */ + +declare export var PlutusDataKind: {| + +ConstrPlutusData: 0, // 0 + +Map: 1, // 1 + +List: 2, // 2 + +Integer: 3, // 3 + +Bytes: 4, // 4 |}; /** @@ -492,34 +491,35 @@ declare export var VoterKind: {| /** */ -declare export var MIRPot: {| - +Reserves: 0, // 0 - +Treasury: 1, // 1 +declare export var RelayKind: {| + +SingleHostAddr: 0, // 0 + +SingleHostName: 1, // 1 + +MultiHostName: 2, // 2 |}; /** */ -declare export var MIRKind: {| - +ToOtherPot: 0, // 0 - +ToStakeCredentials: 1, // 1 +declare export var CborContainerType: {| + +Array: 0, // 0 + +Map: 1, // 1 |}; /** */ -declare export var CborContainerType: {| - +Array: 0, // 0 - +Map: 1, // 1 +declare export var CredKind: {| + +Key: 0, // 0 + +Script: 1, // 1 |}; /** - * Used to choosed the schema for a script JSON string */ -declare export var ScriptSchema: {| - +Wallet: 0, // 0 - +Node: 1, // 1 +declare export var MetadataJsonSchema: {| + +NoConversions: 0, // 0 + +BasicConversions: 1, // 1 + +DetailedSchema: 2, // 2 |}; /** @@ -4045,6 +4045,9 @@ declare export class FixedTransaction { set_body(raw_body: Uint8Array): void; /** + * We do not recommend using this function, since it might lead to script integrity hash. + * The only purpose of this struct is to sign the transaction from third-party sources. + * Use `.sign_and_add_vkey_signature` or `.sign_and_add_icarus_bootstrap_signature` or `.sign_and_add_daedalus_bootstrap_signature` instead. * @param {Uint8Array} raw_witness_set */ set_witness_set(raw_witness_set: Uint8Array): void; @@ -4083,6 +4086,29 @@ declare export class FixedTransaction { * @returns {Uint8Array | void} */ raw_auxiliary_data(): Uint8Array | void; + + /** + * @param {PrivateKey} private_key + */ + sign_and_add_vkey_signature(private_key: PrivateKey): void; + + /** + * @param {ByronAddress} addr + * @param {Bip32PrivateKey} private_key + */ + sign_and_add_icarus_bootstrap_signature( + addr: ByronAddress, + private_key: Bip32PrivateKey + ): void; + + /** + * @param {ByronAddress} addr + * @param {LegacyDaedalusPrivateKey} private_key + */ + sign_and_add_daedalus_bootstrap_signature( + addr: ByronAddress, + private_key: LegacyDaedalusPrivateKey + ): void; } /** * Warning: This is experimental and may be removed or changed in the future. From 08476c7130bfdff081ebe8c13ef2188f68684720 Mon Sep 17 00:00:00 2001 From: lisicky Date: Wed, 4 Sep 2024 06:11:34 +0900 Subject: [PATCH 09/19] bump version --- package-lock.json | 4 ++-- package.json | 2 +- rust/Cargo.toml | 2 +- rust/json-gen/Cargo.lock | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index d2506b91..78537478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cardano-serialization-lib", - "version": "12.0.2-beta.1", + "version": "12.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cardano-serialization-lib", - "version": "12.0.2-beta.1", + "version": "12.1.0", "hasInstallScript": true, "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index 11279965..d4c541f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cardano-serialization-lib", - "version": "12.0.2-beta.1", + "version": "12.1.0", "description": "(De)serialization functions for the Cardano blockchain along with related utility functions", "scripts": { "rust:build-nodejs": "(rimraf ./rust/pkg && cd rust; wasm-pack build --target=nodejs; cd ..; npm run js:ts-json-gen; cd rust; wasm-pack pack) && npm run js:flowgen", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index a8fadb13..b664eab5 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cardano-serialization-lib" -version = "12.0.2-beta.1" +version = "12.1.0" edition = "2018" authors = ["EMURGO"] license = "MIT" diff --git a/rust/json-gen/Cargo.lock b/rust/json-gen/Cargo.lock index 94b02c1a..db579263 100644 --- a/rust/json-gen/Cargo.lock +++ b/rust/json-gen/Cargo.lock @@ -49,7 +49,7 @@ checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "cardano-serialization-lib" -version = "12.0.2-beta.1" +version = "12.1.0" dependencies = [ "bech32", "cbor_event", From cfad11ed900df6a52138db69e72b89c6c076ca64 Mon Sep 17 00:00:00 2001 From: lisicky Date: Wed, 4 Sep 2024 06:17:49 +0900 Subject: [PATCH 10/19] switch version --- example/package-lock.json | 2 +- package-lock.json | 4 ++-- package.json | 2 +- rust/Cargo.toml | 2 +- rust/json-gen/Cargo.lock | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/package-lock.json b/example/package-lock.json index 20211385..097b9101 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -644,7 +644,7 @@ "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "globals": "^12.1.0-beta.1", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", diff --git a/package-lock.json b/package-lock.json index 78537478..d0c6f23b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cardano-serialization-lib", - "version": "12.1.0", + "version": "12.1.0-beta.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cardano-serialization-lib", - "version": "12.1.0", + "version": "12.1.0-beta.1", "hasInstallScript": true, "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index d4c541f4..3887e8bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cardano-serialization-lib", - "version": "12.1.0", + "version": "12.1.0-beta.1", "description": "(De)serialization functions for the Cardano blockchain along with related utility functions", "scripts": { "rust:build-nodejs": "(rimraf ./rust/pkg && cd rust; wasm-pack build --target=nodejs; cd ..; npm run js:ts-json-gen; cd rust; wasm-pack pack) && npm run js:flowgen", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index b664eab5..7d16b483 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cardano-serialization-lib" -version = "12.1.0" +version = "12.1.0-beta.1" edition = "2018" authors = ["EMURGO"] license = "MIT" diff --git a/rust/json-gen/Cargo.lock b/rust/json-gen/Cargo.lock index db579263..72482356 100644 --- a/rust/json-gen/Cargo.lock +++ b/rust/json-gen/Cargo.lock @@ -49,7 +49,7 @@ checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "cardano-serialization-lib" -version = "12.1.0" +version = "12.1.0-beta.1" dependencies = [ "bech32", "cbor_event", From ad24318d3a9486cf77ed62eaf11c16c47a0de586 Mon Sep 17 00:00:00 2001 From: lisicky Date: Thu, 5 Sep 2024 23:39:31 +0900 Subject: [PATCH 11/19] revert version --- example/package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/package-lock.json b/example/package-lock.json index 097b9101..20211385 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -644,7 +644,7 @@ "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^12.1.0-beta.1", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", From 66aeedb82c0243e0c7d296acfa7bc0a2ebd1e8eb Mon Sep 17 00:00:00 2001 From: lisicky Date: Thu, 5 Sep 2024 23:40:02 +0900 Subject: [PATCH 12/19] bump version --- package-lock.json | 4 ++-- package.json | 2 +- rust/Cargo.toml | 2 +- rust/json-gen/Cargo.lock | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index d0c6f23b..78537478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cardano-serialization-lib", - "version": "12.1.0-beta.1", + "version": "12.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cardano-serialization-lib", - "version": "12.1.0-beta.1", + "version": "12.1.0", "hasInstallScript": true, "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index 3887e8bb..d4c541f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cardano-serialization-lib", - "version": "12.1.0-beta.1", + "version": "12.1.0", "description": "(De)serialization functions for the Cardano blockchain along with related utility functions", "scripts": { "rust:build-nodejs": "(rimraf ./rust/pkg && cd rust; wasm-pack build --target=nodejs; cd ..; npm run js:ts-json-gen; cd rust; wasm-pack pack) && npm run js:flowgen", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 7d16b483..b664eab5 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cardano-serialization-lib" -version = "12.1.0-beta.1" +version = "12.1.0" edition = "2018" authors = ["EMURGO"] license = "MIT" diff --git a/rust/json-gen/Cargo.lock b/rust/json-gen/Cargo.lock index 72482356..db579263 100644 --- a/rust/json-gen/Cargo.lock +++ b/rust/json-gen/Cargo.lock @@ -49,7 +49,7 @@ checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "cardano-serialization-lib" -version = "12.1.0-beta.1" +version = "12.1.0" dependencies = [ "bech32", "cbor_event", From 6d89e3c1c3b597ef6aff8b1375f3fbc46ae44755 Mon Sep 17 00:00:00 2001 From: lisicky Date: Sat, 7 Sep 2024 01:27:36 +0900 Subject: [PATCH 13/19] fixed roundtrip, add add_vkey_witness add_bootstrap_witness, transaction_hash functions for FixedTransaction --- rust/src/protocol_types/fixed_tx.rs | 13 +++ .../witnesses/bootstrap_witnesses.rs | 5 + .../witnesses/fixed_tx_witnesses_set.rs | 1 + .../witnesses/transaction_witnesses_set.rs | 1 + .../protocol_types/witnesses/vkeywitnesses.rs | 5 + .../witnesses/fixed_tx_witnesses_set.rs | 2 +- .../witnesses/transaction_witnesses_set.rs | 16 +-- rust/src/tests/protocol_types/fixed_tx.rs | 101 ++++++++++++++++++ 8 files changed, 135 insertions(+), 9 deletions(-) diff --git a/rust/src/protocol_types/fixed_tx.rs b/rust/src/protocol_types/fixed_tx.rs index e79879cb..76ec61a6 100644 --- a/rust/src/protocol_types/fixed_tx.rs +++ b/rust/src/protocol_types/fixed_tx.rs @@ -2,6 +2,7 @@ use crate::error::JsError; use crate::*; #[wasm_bindgen] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct FixedTransaction { pub(crate) body: TransactionBody, pub(crate) body_bytes: Vec, @@ -138,6 +139,18 @@ impl FixedTransaction { self.auxiliary_bytes.clone() } + pub fn transaction_hash(&self) -> TransactionHash { + self.tx_hash.clone() + } + + pub fn add_vkey_witness(&mut self, vkey_witness: &Vkeywitness) { + self.witness_set.add_vkey_witness(vkey_witness.clone()); + } + + pub fn add_bootstrap_witness(&mut self, bootstrap_witness: &BootstrapWitness) { + self.witness_set.add_bootstrap_witness(bootstrap_witness.clone()); + } + pub fn sign_and_add_vkey_signature(&mut self, private_key: &PrivateKey) -> Result<(), JsError> { let vkey_witness = make_vkey_witness(&self.tx_hash, private_key); self.witness_set.add_vkey_witness(vkey_witness); diff --git a/rust/src/protocol_types/witnesses/bootstrap_witnesses.rs b/rust/src/protocol_types/witnesses/bootstrap_witnesses.rs index c1372641..9215bb46 100644 --- a/rust/src/protocol_types/witnesses/bootstrap_witnesses.rs +++ b/rust/src/protocol_types/witnesses/bootstrap_witnesses.rs @@ -58,6 +58,11 @@ impl BootstrapWitnesses { dedup, } } + + #[allow(dead_code)] + pub (crate) fn contains(&self, elem: &BootstrapWitness) -> bool { + self.dedup.contains(elem) + } } impl NoneOrEmpty for BootstrapWitnesses { diff --git a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs index ab71b841..10f3e27e 100644 --- a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs +++ b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs @@ -1,6 +1,7 @@ use crate::*; #[allow(dead_code)] +#[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct FixedTxWitnessesSet { pub(crate) raw_parts: TransactionWitnessSetRaw, pub(crate) tx_witnesses_set: TransactionWitnessSet, diff --git a/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs b/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs index a3bd59b7..7412c618 100644 --- a/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs +++ b/rust/src/protocol_types/witnesses/transaction_witnesses_set.rs @@ -1,6 +1,7 @@ use crate::*; use crate::traits::EmptyToNone; +#[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct TransactionWitnessSetRaw { pub(crate) vkeys: Option>, pub(crate) native_scripts: Option>, diff --git a/rust/src/protocol_types/witnesses/vkeywitnesses.rs b/rust/src/protocol_types/witnesses/vkeywitnesses.rs index f0396fb7..791f0c33 100644 --- a/rust/src/protocol_types/witnesses/vkeywitnesses.rs +++ b/rust/src/protocol_types/witnesses/vkeywitnesses.rs @@ -54,6 +54,11 @@ impl Vkeywitnesses { } Self { witnesses, dedup } } + + #[allow(dead_code)] + pub(crate) fn contains(&self, elem: &Vkeywitness) -> bool { + self.dedup.contains(elem) + } } impl NoneOrEmpty for Vkeywitnesses { diff --git a/rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs b/rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs index b67f086b..3df00197 100644 --- a/rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs +++ b/rust/src/serialization/witnesses/fixed_tx_witnesses_set.rs @@ -15,7 +15,7 @@ impl Deserialize for FixedTxWitnessesSet { where Self: Sized { - let (witness_set, raw_parts) = super::transaction_witnesses_set::deserialize(raw, false)?; + let (witness_set, raw_parts) = super::transaction_witnesses_set::deserialize(raw, true)?; Ok(Self { tx_witnesses_set: witness_set, raw_parts diff --git a/rust/src/serialization/witnesses/transaction_witnesses_set.rs b/rust/src/serialization/witnesses/transaction_witnesses_set.rs index 6967f09e..c3dde252 100644 --- a/rust/src/serialization/witnesses/transaction_witnesses_set.rs +++ b/rust/src/serialization/witnesses/transaction_witnesses_set.rs @@ -225,7 +225,7 @@ pub(super) fn serialize<'se, W: Write>( if let Some(field) = &wit_set.vkeys { if let Some(raw_vkeys) = raw_parts.map(|x| x.vkeys.as_ref()).flatten() { serializer.write_unsigned_integer(0)?; - serializer.write_bytes(raw_vkeys)?; + serializer.write_raw_bytes(raw_vkeys)?; } else if !field.is_none_or_empty() { serializer.write_unsigned_integer(0)?; field.serialize(serializer)?; @@ -234,7 +234,7 @@ pub(super) fn serialize<'se, W: Write>( if let Some(field) = &wit_set.native_scripts { if let Some(raw) = raw_parts.as_ref().map(|x| x.native_scripts.as_ref()).flatten() { serializer.write_unsigned_integer(1)?; - serializer.write_bytes(raw)?; + serializer.write_raw_bytes(raw)?; } else if !field.is_none_or_empty() { serializer.write_unsigned_integer(1)?; //transaction witness set already has deduplicated native scripts @@ -244,7 +244,7 @@ pub(super) fn serialize<'se, W: Write>( if let Some(field) = &wit_set.bootstraps { if let Some(raw) = raw_parts.as_ref().map(|x| x.bootstraps.as_ref()).flatten() { serializer.write_unsigned_integer(2)?; - serializer.write_bytes(raw)?; + serializer.write_raw_bytes(raw)?; } else if !field.is_none_or_empty() { serializer.write_unsigned_integer(2)?; field.serialize(serializer)?; @@ -256,7 +256,7 @@ pub(super) fn serialize<'se, W: Write>( if has_plutus_v1 { if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v1.as_ref()).flatten() { serializer.write_unsigned_integer(3)?; - serializer.write_bytes(raw)?; + serializer.write_raw_bytes(raw)?; } else { serializer.write_unsigned_integer(3)?; plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v1(), serializer)?; @@ -265,7 +265,7 @@ pub(super) fn serialize<'se, W: Write>( if has_plutus_v2 { if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v2.as_ref()).flatten() { serializer.write_unsigned_integer(6)?; - serializer.write_bytes(raw)?; + serializer.write_raw_bytes(raw)?; } else { serializer.write_unsigned_integer(6)?; plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v2(), serializer)?; @@ -274,7 +274,7 @@ pub(super) fn serialize<'se, W: Write>( if has_plutus_v3 { if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_scripts_v3.as_ref()).flatten() { serializer.write_unsigned_integer(7)?; - serializer.write_bytes(raw)?; + serializer.write_raw_bytes(raw)?; } else { serializer.write_unsigned_integer(7)?; plutus_scripts.serialize_as_set_by_version(false, &Language::new_plutus_v3(), serializer)?; @@ -284,7 +284,7 @@ pub(super) fn serialize<'se, W: Write>( if let Some(field) = &wit_set.plutus_data { if let Some(raw) = raw_parts.as_ref().map(|x| x.plutus_data.as_ref()).flatten() { serializer.write_unsigned_integer(4)?; - serializer.write_bytes(&raw)?; + serializer.write_raw_bytes(&raw)?; } else if !field.is_none_or_empty() { serializer.write_unsigned_integer(4)?; //transaction witness set already has deduplicated plutus data @@ -294,7 +294,7 @@ pub(super) fn serialize<'se, W: Write>( if let Some(field) = &wit_set.redeemers { if let Some(raw) = raw_parts.as_ref().map(|x| x.redeemers.as_ref()).flatten() { serializer.write_unsigned_integer(5)?; - serializer.write_bytes(raw)?; + serializer.write_raw_bytes(raw)?; } else if !field.is_none_or_empty() { serializer.write_unsigned_integer(5)?; field.serialize(serializer)?; diff --git a/rust/src/tests/protocol_types/fixed_tx.rs b/rust/src/tests/protocol_types/fixed_tx.rs index 84edc34d..7cb14593 100644 --- a/rust/src/tests/protocol_types/fixed_tx.rs +++ b/rust/src/tests/protocol_types/fixed_tx.rs @@ -70,3 +70,104 @@ fn round_trip_nonstandart_body() { assert_ne!(tx2.to_bytes(), original_tx.to_bytes()); } + +#[test] +fn fixed_tx_add_signature() { + let mut tx = FixedTransaction::from_hex("84a7009F8258208b9c96823c19f2047f32210a330434b3d163e194ea17b2b702c0667f6fea7a7a00FF0d80018182581d6138fe1dd1d91221a199ff0dacf41fdd5b87506b533d00e70fae8dae8f1abfbac06a021a0002b645031a03962de305a1581de1b3cabd3914ef99169ace1e8b545b635f809caa35f8b6c8bc69ae48061abf4009040e80a100828258207dc05ac55cdfb9cc24571d491d3a3bdbd7d48489a916d27fce3ffe5c9af1b7f55840d7eda8457f1814fe3333b7b1916e3b034e6d480f97f4f286b1443ef72383279718a3a3fddf127dae0505b01a48fd9ffe0f52d9d8c46d02bcb85d1d106c13aa048258201b3d6e1236891a921abf1a3f90a9fb1b2568b1096b6cd6d3eaaeb0ef0ee0802f58401ce4658303c3eb0f2b9705992ccd62de30423ade90219e2c4cfc9eb488c892ea28ba3110f0c062298447f4f6365499d97d31207075f9815c3fe530bd9a927402f5f6").unwrap(); + let private_key_1 = Bip32PrivateKey::generate_ed25519_bip32().unwrap().to_raw_key(); + let private_key_2 = Bip32PrivateKey::generate_ed25519_bip32().unwrap().to_raw_key(); + + assert_eq!(tx.witness_set().vkeys().unwrap().len(), 2); + + let vkey_witness_1 = make_vkey_witness(&tx.transaction_hash(), &private_key_1); + let vkey_witness_2 = make_vkey_witness(&tx.transaction_hash(), &private_key_2); + tx.add_vkey_witness(&vkey_witness_1); + tx.sign_and_add_vkey_signature(&private_key_2).unwrap(); + + let tx2 = FixedTransaction::from_bytes(tx.to_bytes()).unwrap(); + assert_eq!(&tx.body(), &tx2.body()); + assert_eq!(&tx.witness_set(), &tx2.witness_set()); + + let vkey_witnesses = tx2.witness_set().vkeys().unwrap(); + assert_eq!(vkey_witnesses.len(), 4); + assert!(vkey_witnesses.contains(&vkey_witness_1)); + assert!(vkey_witnesses.contains(&vkey_witness_2)); +} + + +#[test] +fn fixed_tx_add_daedalus_boostrap_signature() { + let mut tx = FixedTransaction::from_hex("84a7009F8258208b9c96823c19f2047f32210a330434b3d163e194ea17b2b702c0667f6fea7a7a00FF0d80018182581d6138fe1dd1d91221a199ff0dacf41fdd5b87506b533d00e70fae8dae8f1abfbac06a021a0002b645031a03962de305a1581de1b3cabd3914ef99169ace1e8b545b635f809caa35f8b6c8bc69ae48061abf4009040e80a100828258207dc05ac55cdfb9cc24571d491d3a3bdbd7d48489a916d27fce3ffe5c9af1b7f55840d7eda8457f1814fe3333b7b1916e3b034e6d480f97f4f286b1443ef72383279718a3a3fddf127dae0505b01a48fd9ffe0f52d9d8c46d02bcb85d1d106c13aa048258201b3d6e1236891a921abf1a3f90a9fb1b2568b1096b6cd6d3eaaeb0ef0ee0802f58401ce4658303c3eb0f2b9705992ccd62de30423ade90219e2c4cfc9eb488c892ea28ba3110f0c062298447f4f6365499d97d31207075f9815c3fe530bd9a927402f5f6").unwrap(); + let private_key_1 = Bip32PrivateKey::generate_ed25519_bip32().unwrap(); + let private_key_2 = Bip32PrivateKey::generate_ed25519_bip32().unwrap(); + let legacy_private_key_1 = LegacyDaedalusPrivateKey::from_bytes(&private_key_1.as_bytes()).unwrap(); + let legacy_private_key_2 = LegacyDaedalusPrivateKey::from_bytes(&private_key_2.as_bytes()).unwrap(); + let addr = ByronAddress::from_base58("Ae2tdPwUPEZ6r6zbg4ibhFrNnyKHg7SYuPSfDpjKxgvwFX9LquRep7gj7FQ").unwrap(); + + assert_eq!(tx.witness_set().bootstraps().unwrap_or_else(|| BootstrapWitnesses::new()).len(), 0); + + let boostrap_witness_1 = make_daedalus_bootstrap_witness(&tx.transaction_hash(), &addr, &legacy_private_key_1); + let boostrap_witness_2 = make_daedalus_bootstrap_witness(&tx.transaction_hash(), &addr, &legacy_private_key_2); + tx.add_bootstrap_witness(&boostrap_witness_1); + tx.sign_and_add_daedalus_bootstrap_signature(&addr, &legacy_private_key_2).unwrap(); + + let tx2 = FixedTransaction::from_bytes(tx.to_bytes()).unwrap(); + assert_eq!(&tx.body(), &tx2.body()); + assert_eq!(&tx.witness_set(), &tx2.witness_set()); + + let boostraps = tx2.witness_set().bootstraps().unwrap(); + assert_eq!(boostraps.len(), 2); + assert!(boostraps.contains(&boostrap_witness_1)); + assert!(boostraps.contains(&boostrap_witness_2)); +} + + +#[test] +fn fixed_tx_add_icarus_boostrap_signature() { + let mut tx = FixedTransaction::from_hex("84a7009F8258208b9c96823c19f2047f32210a330434b3d163e194ea17b2b702c0667f6fea7a7a00FF0d80018182581d6138fe1dd1d91221a199ff0dacf41fdd5b87506b533d00e70fae8dae8f1abfbac06a021a0002b645031a03962de305a1581de1b3cabd3914ef99169ace1e8b545b635f809caa35f8b6c8bc69ae48061abf4009040e80a100828258207dc05ac55cdfb9cc24571d491d3a3bdbd7d48489a916d27fce3ffe5c9af1b7f55840d7eda8457f1814fe3333b7b1916e3b034e6d480f97f4f286b1443ef72383279718a3a3fddf127dae0505b01a48fd9ffe0f52d9d8c46d02bcb85d1d106c13aa048258201b3d6e1236891a921abf1a3f90a9fb1b2568b1096b6cd6d3eaaeb0ef0ee0802f58401ce4658303c3eb0f2b9705992ccd62de30423ade90219e2c4cfc9eb488c892ea28ba3110f0c062298447f4f6365499d97d31207075f9815c3fe530bd9a927402f5f6").unwrap(); + let private_key_1 = Bip32PrivateKey::generate_ed25519_bip32().unwrap(); + let private_key_2 = Bip32PrivateKey::generate_ed25519_bip32().unwrap(); + let addr = ByronAddress::from_base58("Ae2tdPwUPEZ6r6zbg4ibhFrNnyKHg7SYuPSfDpjKxgvwFX9LquRep7gj7FQ").unwrap(); + + assert_eq!(tx.witness_set().bootstraps().unwrap_or_else(|| BootstrapWitnesses::new()).len(), 0); + + let boostrap_witness_1 = make_icarus_bootstrap_witness(&tx.transaction_hash(), &addr, &private_key_1); + let boostrap_witness_2 = make_icarus_bootstrap_witness(&tx.transaction_hash(), &addr, &private_key_2); + tx.add_bootstrap_witness(&boostrap_witness_1); + tx.sign_and_add_icarus_bootstrap_signature(&addr, &private_key_2).unwrap(); + + let tx2 = FixedTransaction::from_bytes(tx.to_bytes()).unwrap(); + assert_eq!(&tx.body(), &tx2.body()); + assert_eq!(&tx.witness_set(), &tx2.witness_set()); + + let boostraps = tx2.witness_set().bootstraps().unwrap(); + assert_eq!(boostraps.len(), 2); + assert!(boostraps.contains(&boostrap_witness_1)); + assert!(boostraps.contains(&boostrap_witness_2)); +} + +#[test] +fn fixed_transaction_with_plutus_witnesses() { + let hex = "84a800848258201855904b87b88b6f6f570baf2de13ac40409bde1ac118831c6b017eac208f58f018258205e5e5b729ec780ff30c5792b19b72c9988bec8a03d7e390285f27e40da3c19e20082582064788d05156079bd701f81ea1a6bd92344347ce78004fcce79f05fe175b42e9c03825820d4bf5b955f1d6e1ff8c41579d5a339c6d9a2c35a8c1ee8c58d5f98516c091ab0000d818258205e5e5b729ec780ff30c5792b19b72c9988bec8a03d7e390285f27e40da3c19e2000184a2005839012ebacbaf16275a0184357de07c81d4a895f29343c235974f3b4c1d7d52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c2011a055adc18a2005839012ebacbaf16275a0184357de07c81d4a895f29343c235974f3b4c1d7d52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c201821a00150bd0a1581c2f2e0404310c106e2a260e8eb5a7e43f00cff42c667489d30e179816a14d3136393230383238303030303001a200583901c49a4ce8541f2853f03a42e97c422771999427bfc0f204ffadf3ffded68f19e171c74e2c0de746498908950c618492896cd22202f5ae1d00011a09e8f6b3a300583911e1317b152faac13426e6a83e06ff88a4d62cce3c1634ab0a5ec1330952563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c201821b0000001b3657ca66a4581c0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1a15820c2dd32c8e1339fb458a172a9e855871a06314644bc33b596d85cf920962e7acd01581c13aa2accf2e1561723aa26871e071fdf32c867cff7e7d50ad470d62fa1474d494e5357415001581c9f452e23804df3040b352b478039357b506ad3b50d2ce0d7cbd5f806a1434354561a00421407581ce4214b7cce62ac6fbba385d164df48e157eae5863521b4b67ca71d86a15820c2dd32c8e1339fb458a172a9e855871a06314644bc33b596d85cf920962e7acd1a0002804802820058209faffd83c380add35b6ac693605ed8e2e13d7fd4edb036fc5f6e16a228a20c26021a000c89b9031a05d01df10e81581c2ebacbaf16275a0184357de07c81d4a895f29343c235974f3b4c1d7d0b582020d91590476f01856bfcf05ea07a605508129465a811fe7ab3875c278c81aaf40758202f74062bfa12ab744d8c1988e8841bff514903aa8dd12cfecfec04afd596be77a40081825820d2beea31ad3bbc59b0d50a84a9395e9f55dca859ac7a78da7b0c1ea946fdd36358400732d420184741ae707903f76032f75198cb9f3a37a69b10c769c1d07e8d6819d6884b528ff59eddf36c1f4adda563556c4d5f15704ee3613fa6cdd49ec36a03038259014f59014c01000032323232323232322223232325333009300e30070021323233533300b3370e9000180480109118011bae30100031225001232533300d3300e22533301300114a02a66601e66ebcc04800400c5288980118070009bac3010300c300c300c300c300c300c300c007149858dd48008b18060009baa300c300b3754601860166ea80184ccccc0288894ccc04000440084c8c94ccc038cd4ccc038c04cc030008488c008dd718098018912800919b8f0014891ce1317b152faac13426e6a83e06ff88a4d62cce3c1634ab0a5ec133090014a0266008444a00226600a446004602600a601a00626600a008601a006601e0026ea8c03cc038dd5180798071baa300f300b300e3754601e00244a0026eb0c03000c92616300a001375400660106ea8c024c020dd5000aab9d5744ae688c8c0088cc0080080048c0088cc00800800555cf2ba15573e6e1d200201591e1b591e1801000032323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232222323232533533355333573460cc0042646424446600200a0086eb4d5d09aba25002375a6ae85400454ccd5cd1832801099091118010021bad357426aae7800c54ccd5cd1832001099190911198018028021bad357426ae894008c0ccd5d0a80082e1119191a827911111a80391191111aa99a9824806108008b1119191a9a9a80103102d91191919191919191aa99a982a89119982d91299a99820a8071a80103409980200100088008008020b03c9111919191919191919191919191982a299a8050a99aa8100999ab9a3094013303a307908101330820106700b06706e0060063305433355307908101305c05a305953353502b2233500206e2071210011635014222222207a33054353501422208e0122350012322533355333500a2153335004215333500c2130054984c011261533350052130054984c0112603c04f15333500b2130044984c00d261533350042130044984c00d2603b153335003205003a04f153335003215333500b2130044984c00d261533350042130044984c00d2603b04e15333500a2130034984c009261533350032130034984c0092603a153350010700820108201070253335002215333500a21533350042133303a03b00200116161604e15333500921533350032133303903a00200116161604d04e33054330500153306f00b02733054330533306301602548008cc150cc14ccc18c02c0952002330543305333063001010002330543333084012222533500315335002135001222223305d3305c0053306c01402b3305d3305c0043306c01402a3305d3305c00300c3305d3305c0023306c0140193305c001304800d0910122153350041622153350071622153350081622133300c003001323232323232323533307d0050070272222225335330743305100248000cc1440052000161333335003235500b2222223501d222223501b22235051222223232323232323232323253353308b013308b013306e00848000cc1b802920003308b013306d00201e3308b0153353306e00a00315335330870100e07013308b013308a013309a010110703370066e0402800c060cc22804cc2680404411c0084cc22c04cc22804cc268040441c0060cc22c04cc22804cc2680404411c008cc22804cdc08050019984d008088070a99a998370041a802055008a99a99843808078380998458099845009984d0080883819b80337020106a008154020306611402661340202208e00426611602661140266134020220e003066116026611402661340202208e004661140266e04020d40102a804cc2680404403c4cc22c04cc22804cc2680404411c008cc22804cc268040441c0060cc22c04cc20c04048070cc2080404006c4c8c8c8ccccc2c80400c008cdc019b800180050013370002e002a66a0082605466e0800c00840594cd400c4cccc0a005406406005c520003370002e00866e0005cd40102a80458c27c04028d40082a404d40042a404d54cd54ccd5cd19b8900148000278044c94ccd5cd19b890014800027c044c94ccd5cd19b8900148000280044c28404ccc2ec0400c0080054ccd5cd19b8900400610041006350020ad0121001160b901350010b0015333573466e2400400c54ccd5cd19b880010031330a8010023370666e080080400444cc2a0040080104cc2a004cdc199b820040110100043370666e080040380414cd4cc1fc01c1a04cdc0998490081100399b80011010133092010220073370666e080040300354cd4cc1f40101984cdc0998480081000219b8000f00e133090010200042235500c2222223501e222223501c222350522222232323232323232323253353308b013306e00748000cc22c04cc1b4008074cc22c04cc22c04cc22804cc2680404011c008cc22804cc268040401c005ccc22c04cc20c0404406ccc2080403c0684c8c8c8c8ccccc2cc0400c008cdc019b800180060013370002e002a66a00a2605666e0800c00840594cd40104cccc0a405406406005c52000350020b301350010b60153353330690870100e01e1330ae013370002c00e02a26615c0202c66e0005401c58c27c04024cdc199b820010123370200400266604400600266e0ccdc0981219b803370400400466e08cdc119b82337049004241941e90680780200198600080199b824801120ca0f350050a70130be01001350030a60153353308001001069133702661260204600266e000440404cc24c0408c004d400428804d54cd4ccc1801f80140544ccc2d0040140340304ccc2d004010030034888d400c88ccc2e40401401000c88d54030888888d407888888d4070888d414888888c8c8c8c94cd4cc21804cc1a4009200033086013306800101833086015335330820101906b13308501330950100b0193370000202426610c026610a026612a020160320026610a026612a020160d60246610c02660fc01802c660fa01402a2a66a6660c8104020120322666661540266e00044008cdc08080008078070068999998550099b810110013370002000401e01c01a2c66603e6a00614c026a00614a02002a66a66100020020d2266e04cc24c0408c004cdc0008808099849808118009a800851009aa99a99983003f00280a899985a00802806806099985a008020060069111a8019119985c80802802001911aa8061111111a80f111111a80e1111a82911111191919191919299a998440099835802240006611002660d80020086611002a66a66108020360da266110026610e026612e0201a03666e00068050cc21c04cc25c04034014cdc08020008a99a99842008028368998440099843809984b8080680d80d19843809984b8080680299b8033702008002028266110026610e026612e0201a03603466110026610e026612e0201a00a66e04010004cc21c04cc25c040341b4050cc22004cc20004038060cc1fc03005c54cd4ccc1982100402c06c4ccccc2b004cdc000980099b8101201a01101000f1333330ac013370202603466e0004800404404003c594cd54ccd5cd19b880190011309f013370066e0ccdc119b82002019483403ccdc119b81001019483283d200209e012100116350040a601350030a60153353308001001069133702661260204600266e000440404cc24c0408c004d400428804d54cd4ccc1801f80140544ccc2d0040140340304ccc2d004010030034888d400c88ccc2e40401401000c88d54030888888d407888888d4070888d414888888c8c8c8c94cd4cc21804cc1a4011200033086013308601330680030193306800201833086015335330820100906b133086013308501330950100b009337000060246610a026612a020160100042a66a66104020100d626610c026610a026612a0201601066e00008048cc21404cc2540402c02400c4cc21804cc21404cc2540402c02400ccc21804cc21404cc2540402c020008cc21404cc2540402c1ac048cc21804cc1f8030058cc1f40280544c8c8c8ccccc2b40400800ccdc019b8101200700133700022002a66a0082604a66e0800800c40414cd400c4cccc08c03c04c048044520003370202400866e0404000858c26804010cdc199b8200200e00d3370666e08004038030cc244040840f8888c8cdc199b820010033370066e0801120d00f0013370400290650791112999ab9a3371200890000a4000264a666ae68cdc48008028a4000264a666ae68cdc4800a400029000080099b833370400466e04004014cdc019b8200148028014c014cdc10018011192999ab9a33710004900004d808a999ab9a30a10100214800054ccd5cd1851008010a40042a666ae68c28c04008520021330010023370066e0c009200448008c254048894ccd5cd19b880010021330030013370666e00cdc1802000800a4008200426660f2002006046464a666ae68c27c04d55ce80089919191919191919191919191919091999998008050048040028018011bad357426ae88008dd69aba100135744010a666ae68c2b4040084c8c8488888cc01001c018dd69aba135744a0046660f8eb9d71aba15001153335734615802004264642444446600200e00c6eb4d5d09aba25002375a6ae85400454ccd5cd18558080109909111118028031bad357426aae7801854ccd5cd18550080109919091111198010038031bad357426ae894008ccc1f1d73ae35742a0022a666ae68c2a4040084c8c8488888cc00c01c018dd69aba135744a0046660f8eb9d71aba150010a101135573c00a6aae74010cc1e1d71aba100530743574200a60e66ae84014dd51aba1001357440026ae88004d5d10009aab9e0010970137540026a002104026a00810c0260c82446660d444a66a660b066606c0d46a004104026a03c1040266606c0a06a6a0040fc0ee05e266008004002200200202a60c82446660d444a66a660b066606c0a06a0040ee6a0200ee66606c0a06a0040ee05e2660080040022002002026666660f0660c602c044660c602c04203e660c602c02003c660a8660a0044607a008660a8660a0042607c008660a8024660a8a66a60c82446660d444a66a660a66aa03a104026a6a0040ee1040226600800400220020020260d6442a66a0020fe440dea66a6660640a600490000998299981d183c840809984100833800a40042660a66607460f21020266104020ce0029000183800999b8100101d303d001333066059008010305333307f22322325333573466e1c010dc680488010a999ab9a308f0100415333573466e1d205a500313370290001980299b800044800800800400454ccd5cd19b885002481805854ccd5cd19b8950023370090302402426600866e0000d20023370066e08005201433702a00490300b099b8e0060014800120001533500400115335501a13335734611a026606860e60f6660f80c200a0c20d00022a66a0062a66aa0320022666ae68c23804cc0ccc1c81e8cc1ec18001018019c0044ccd5cd18460099819183883c9983d02f80182f833299a9983d91299a8008321109a80111299a9982b00101089834800898030019a9a99a983b03c00501083883610a99a8008b1109a80111299a8018a99a99827800a400420042c112022c666ae68cdc49982c800803240000c80ba6a0020d4a66a60b02446660bc44a66a66088a0226a0040d6266008004002200200200e2c0f8660ce02c6a00a0d460c2006a66a60a42446660b044a66a660826aa0160e06a6a6a0040d80ca0e026600800400220020020060b2442a66a0020da440ba60ba0026a0280d4660b40020246a6a0080c80be26a6a0020c20b4a66a609601c420022c2a66a660600040320ba266060002032603200e6068010464646a09c4444464646464646464660706606a00c0066607066068660a600c018660a6006018660706606e6608e6a6a66a60c60ca00401e0bc0b2660b601201090011981c1981f998188070009981c1981b9811800a40006607066068604201c60420026607066068604401c60440026606e604801c6048002660706606a60aa00a09666070a66a609024466609c44a66a60a26a6a0040c40b8266008004002200200200809e442a66a0020c6440a6a66a609024466609c44a66a60a26a0040b8266008004002200200260b000e09e442a66a0020c6440a666609a08000600860a40066a0020aca66a608824466609444a66a660666a6a6a00e0bc0ae0c46a6a0040ae0c4266008004002200200260a80062c0d06a0100ba6a6a0020b00a6a66a608400c420022c603000c606600e4464646a09e44444a66a6a00e440a8426464646464646464646464646607e660700286660aa09000800c6607e66076014660b40060246607e6607e6607c6609c6a0040c00120106607e6606e6a0040bc6a01a0d26606c6a0040be6a01a0ca6607e6607866aa60ce0d846a00244660ca00466aa60d40de46a00244660d0004666a0026e012000700466e0000520000013304000b3500922330723306400233072330640010090540540033303f3303e3304e3535335306a06c0010160650603306200f00e48008cc0fccc0f0c1700181494cd4c13c488ccc154894cd4c160d4d40081a418c4cc010008004400400400c1588854cd40041a888168c168014cd4c1a01a800c04cd40041754cd4c12c488ccc144894cd4cc0dcd4d4030194178d40081784cc010008004400400400c581bcc160004d403418cccd4080178d4d4080188178004cc11800c004cc164020d4004170cc140004020d4d40041681554cd4c11001c8400458124c06401cc0d0020448004584d55cf0011aab9d0013754004444a66a6600600400207809c46a0020b0246666666600204044a666ae68cdc38010008020a999ab9a3371200400203203044666ae68cdc400100081b01e802802001912999ab9a337120040022002200444a666ae68cdc4801000880108008881f11199ab9a3371000400207406644666ae68cdc480100081c81911199ab9a337120040020620706607c91100488100223333550023303f2233350050480010023500304222337000029001000a4000660784446006600400240026607666076e01200070246a0024444400a46a0020a246a0024407246a0024406c464a666ae68c140d55ce8008991919191981e2999ab9a305435573a00626464646464646464646464646464646464646464646424666666666600201a01801601401201000e00a00600460446ae84d5d10011980f1981dbae2001357420026ae88008cc071d71aba100135744016a666ae68c190d55ce804899191919827a999ab9a306735573a004264660a066038eb4d5d0800980d9aba1357440026aae7800817d4ccd5cd18339aab9d001132330503301c75a6ae84004c06cd5d09aba200135573c0020be6ea8d5d09aba200237546ae84004d55cf00482e1980c9981b019bad35742014660300326ae84028ccc059d70029aba100a33301575c0086ae84028cc054008d5d08051980a1192999ab9a306035573a0022646609260326ae84004c010d5d09aba200135573c0020b06ea8004d5d08051192999ab9a305f35573a002264646660b060606ae84008ccc059d70029aba10013303375c6ae84d5d10009aba200135573c0020ae6ea8004cc045d73ad37546ae84004d5d10009aba2001357440026ae88004d5d10009aba200135573c006098a666ae68c15c0044c848888c010014c02cd5d09aab9e00215333573460ac00226424444600400a60486ae84d55cf0010a999ab9a3055001132122223001005300c357426aae7800854ccd5cd182a0008990911118018029bae357426aae78008130d55ce8009baa357426ae88008dd51aba100135573c0020906ea80048c94ccd5cd182800081e8a999ab9a304f00102b04735573a6ea800488c8c94ccd5cd18290008058a999ab9a3051001130193004357426aae7800854ccd5cd18280008050241aab9d00137540024464460046eac004c10888cccd55cf8009014119198239981c98031aab9d001300535573c00260086ae8800cd5d0801020919118011bac00130402233335573e002404c46608860086ae84008c00cd5d100101f91919192999ab9a305300211222203515333573460a4004220922a666ae68c1440084c8c848888888cc004024020dd69aba135744a0046eb8d5d0a8008a999ab9a3050002132321222222233002009008375c6ae84d5d128011bae35742a0022a666ae68c13c0084c8c848888888cc018024020dd71aba135744a004603a6ae85400454ccd5cd1827001099091111111803804180e9aba135573c0062a666ae68c1340084c848888888c014020c074d5d09aab9e003045135573c0046aae74004dd50009192999ab9a304a35573a0022646606660086ae84004dd69aba1357440026aae78004108dd50009192999ab9a304935573a00226eb8d5d09aab9e0010413754002220582205444a66a00442a66a00442660240040020462a66a0024046068446a004446a006446666010008006004002446a004444446a00c44444a66a6601e01400a2a66a6601e0120082a666ae68cdc38040018a999ab9a3370e00e0042a66a00c42a66a004426a004446a004446a00a446a00444a66a666602e00c00a0040022a66a00e42a66a008426604800400206a2a66a006406a08c0680562a66a002405607805405405405444446466a00a466a0084a666ae68cdc78010008018121013919a802101392999ab9a3371e0040020060482a66a00642a66a0044266a004466a00446601200400244405444466a0084054444a666ae68cdc38030018a999ab9a3370e00a0042660220080020520520442a66a00240440664466a004466a00446601c0040024046466a004404646601c004002446a004446a00644a666ae68cdc780200109980780180081091199aa9815019180680191a80091199aa981681a980800311a80091199a800919805a40000020144660160029000000998030010009981280100a91199ab9a3370e00400202c03a44a66a00420020324466aa605205c46a002446604e004666a002466aa605a06446a0024466056004601800200244666010016004002466aa605a06446a0024466056004601600200266600600c004002444666aa605005c06466aa605205c46a002446604e0046010002666aa605005c446a00444a66a666aa6054064601a01646a002446601400400a00c200626606c00800602800266aa605205c46a002446604e0046606844a66a002260120064426a00444a66a6601800401022444660040140082600c00600800442444600200842444600600844666ae68cdc780100080800b9980e80080a11299a801012080091980e11199a8018128010009a80080f9192999ab9a303435573a00226464646466666042666016eb9d71aba100433300b75ceb8d5d08019bad357420046eb4d5d0800998051192999ab9a303a35573a0022646604660146ae84004cc035d71aba1357440026aae780040c8dd50009aba1357440026ae88004d5d10009aba200135573c0020586ea80048c94ccd5cd18199aab9d0011323301c3005357420026600c0086ae84d5d10009aab9e00102b375400246464a666ae68c0d00044c8c8c8c8c8488ccc00401801000cdd69aba1357440046eb4d5d08009aba2002375a6ae84004d55cf0010a999ab9a3033001130103004357426aae780080acd55ce8009baa0012323253335734606600226424460020066eb8d5d09aab9e00215333573460640022601e6eb8d5d09aab9e00202a35573a0026ea800488c8c94ccd5cd18190008980798021aba135573c0042a666ae68c0cc0040380a8d55ce8009baa001222325333573460626aae740044c8cc068c014d5d080098021aba1357440026aae780040a4dd5000911a8009119198131119a800a4000446a00444a666ae68cdc7801004898038008980300180298129119a800a4000446a00444a666ae68cdc7801003880089803001919a80081100211a800911a80111111111111999a805900b900b900b9199aa981101500b11a80091299a998090010020980c00180b805912999ab9a3371e6a0040346a0020342666ae68cdc39a80100b1a80080b001805003880b91180f11299a80088019109980300118020009299a800900b0019111a801111299a800909a8029111111111299aa99a999aa981001400a11a800912999ab9a3371e00401c2602c00602a0044260286a0020440244260240022c2c2006424460040066601444a66a0044200620020022018446602e44a66a00203c4426a00444a666ae68cdc78010038a99a8008111109a80111299a8018a999ab9a302d00113301400b0020262202813006003002235001222222222200a2350012201c23500122222222220092220032220012220023333300248811c0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb10048811ce4214b7cce62ac6fbba385d164df48e157eae5863521b4b67ca71d8600330014891c13aa2accf2e1561723aa26871e071fdf32c867cff7e7d50ad470d62f004881074d494e535741500048811c2f2e0404310c106e2a260e8eb5a7e43f00cff42c667489d30e179816004881054f574e455200221233001003002222221233333001006005004003002300b22112225335001135003006221333500500c300400233355300700f0050040012200130092211222533500110022213300500233355300700d005004001300822112253350010052213300f30040023355300600b00400111001220023005221225333573466e20005200013005490103505436001533500213005491035054370022153335734602c0062004266a600c01000266e0400d2002253357380022c240026004444a66a00220044426a004446600e66601000400c00200660024444a66a00220044426a00444a666ae68c0500044ccc02001c01800c4ccc02001ccc028ccc02c01c00800401800c8c8c00400488cc00cc00800800488488cc00401000c88848ccc00401000c00854cd5ce2490350543100162215335001100200715335738921001622222222007220053704904d0f910b111110021b8748000dc3a40046e1d2004370e90031b8748020dc3a40146e1d200c010482d8799fd8799f4040ffd8799f581c9f452e23804df3040b352b478039357b506ad3b50d2ce0d7cbd5f80643435456ff1a266f99051a2a61c1b8d8799fd8799fd8799fd8799f581caafb1196434cb837fd6f21323ca37b302dff6387e8a84b3fa28faf56ffd8799fd8799fd8799f581c52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c2ffffffffd87a80ffffffd8799fd8799fd8799f581cc49a4ce8541f2853f03a42e97c422771999427bfc0f204ffadf3ffdeffd8799fd8799fd8799f581cd68f19e171c74e2c0de746498908950c618492896cd22202f5ae1d00ffffffffd8799fd8799f581cc49a4ce8541f2853f03a42e97c422771999427bfc0f204ffadf3ffdeffd8799fd8799fd8799f581cd68f19e171c74e2c0de746498908950c618492896cd22202f5ae1d00ffffffffd87a80d8799fd8799f4040ff1a0986e152ff1a001e84801a001e8480ff0582840002d8799fd8799fd8799f581c2ebacbaf16275a0184357de07c81d4a895f29343c235974f3b4c1d7dffd8799fd8799fd8799f581c52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c2ffffffff00ff821a002c2bbd1a33732a0d840003d879808219c7841a0115b9d6f5f6"; + let tx = Transaction::from_hex(hex).unwrap(); + let mut fixed_tx = FixedTransaction::from_hex(hex).unwrap(); + assert_eq!(tx.body(), fixed_tx.body()); + assert_eq!(tx.witness_set(), fixed_tx.witness_set()); + assert_eq!(tx.is_valid(), fixed_tx.is_valid()); + assert_eq!(tx.auxiliary_data(), fixed_tx.auxiliary_data()); + + assert_eq!(fixed_tx.witness_set().vkeys().unwrap().len(), 1); + + let private_key_1 = Bip32PrivateKey::generate_ed25519_bip32().unwrap().to_raw_key(); + let vkey_witness_1 = make_vkey_witness(&fixed_tx.transaction_hash(), &private_key_1); + fixed_tx.sign_and_add_vkey_signature(&private_key_1).unwrap(); + + assert_eq!(fixed_tx.witness_set().vkeys().unwrap().len(), 2); + + let fixed_tx_roundtrip = FixedTransaction::from_bytes(fixed_tx.to_bytes()).unwrap(); + assert_eq!(fixed_tx_roundtrip.body(), fixed_tx.body()); + assert_eq!(fixed_tx_roundtrip.witness_set(), fixed_tx.witness_set()); + + assert!(fixed_tx_roundtrip.witness_set().vkeys().unwrap().contains(&vkey_witness_1)); + assert_eq!(fixed_tx.transaction_hash(), fixed_tx_roundtrip.transaction_hash()); +} \ No newline at end of file From 4ac086c2f17444e4652006c29231d492a30c92b3 Mon Sep 17 00:00:00 2001 From: lisicky Date: Sat, 7 Sep 2024 01:27:52 +0900 Subject: [PATCH 14/19] update js.flow --- rust/pkg/cardano_serialization_lib.js.flow | 411 +++++++++++---------- 1 file changed, 213 insertions(+), 198 deletions(-) diff --git a/rust/pkg/cardano_serialization_lib.js.flow b/rust/pkg/cardano_serialization_lib.js.flow index 7db77f09..5d7af25c 100644 --- a/rust/pkg/cardano_serialization_lib.js.flow +++ b/rust/pkg/cardano_serialization_lib.js.flow @@ -30,80 +30,53 @@ declare export function decrypt_with_password( ): string; /** - * @param {string} json - * @param {$Values< - typeof - PlutusDatumSchema>} schema - * @returns {PlutusData} - */ -declare export function encode_json_str_to_plutus_datum( - json: string, - schema: $Values -): PlutusData; - -/** - * @param {PlutusData} datum - * @param {$Values< - typeof - PlutusDatumSchema>} schema - * @returns {string} - */ -declare export function decode_plutus_datum_to_json_str( - datum: PlutusData, - schema: $Values -): string; - -/** - * @param {Uint8Array} bytes - * @returns {TransactionMetadatum} + * @param {Address} address + * @param {TransactionUnspentOutputs} utxos + * @param {TransactionBuilderConfig} config + * @returns {TransactionBatchList} */ -declare export function encode_arbitrary_bytes_as_metadatum( - bytes: Uint8Array -): TransactionMetadatum; +declare export function create_send_all( + address: Address, + utxos: TransactionUnspentOutputs, + config: TransactionBuilderConfig +): TransactionBatchList; /** - * @param {TransactionMetadatum} metadata - * @returns {Uint8Array} + * @param {Transaction} tx + * @param {LinearFee} linear_fee + * @returns {BigNum} */ -declare export function decode_arbitrary_bytes_from_metadatum( - metadata: TransactionMetadatum -): Uint8Array; +declare export function min_fee(tx: Transaction, linear_fee: LinearFee): BigNum; /** - * @param {string} json - * @param {$Values< - typeof - MetadataJsonSchema>} schema - * @returns {TransactionMetadatum} + * @param {ExUnits} ex_units + * @param {ExUnitPrices} ex_unit_prices + * @returns {BigNum} */ -declare export function encode_json_str_to_metadatum( - json: string, - schema: $Values -): TransactionMetadatum; +declare export function calculate_ex_units_ceil_cost( + ex_units: ExUnits, + ex_unit_prices: ExUnitPrices +): BigNum; /** - * @param {TransactionMetadatum} metadatum - * @param {$Values< - typeof - MetadataJsonSchema>} schema - * @returns {string} + * @param {Transaction} tx + * @param {ExUnitPrices} ex_unit_prices + * @returns {BigNum} */ -declare export function decode_metadatum_to_json_str( - metadatum: TransactionMetadatum, - schema: $Values -): string; +declare export function min_script_fee( + tx: Transaction, + ex_unit_prices: ExUnitPrices +): BigNum; /** - * @param {Address} address - * @param {TransactionUnspentOutputs} utxos - * @param {TransactionBuilderConfig} config - * @returns {TransactionBatchList} + * @param {number} total_ref_scripts_size + * @param {UnitInterval} ref_script_coins_per_byte + * @returns {BigNum} */ -declare export function create_send_all( - address: Address, - utxos: TransactionUnspentOutputs, - config: TransactionBuilderConfig -): TransactionBatchList; +declare export function min_ref_script_fee( + total_ref_scripts_size: number, + ref_script_coins_per_byte: UnitInterval +): BigNum; /** * @param {TransactionHash} tx_body_hash @@ -231,94 +204,75 @@ declare export function encode_json_str_to_native_script( ): NativeScript; /** - * @param {Transaction} tx - * @param {LinearFee} linear_fee - * @returns {BigNum} - */ -declare export function min_fee(tx: Transaction, linear_fee: LinearFee): BigNum; - -/** - * @param {ExUnits} ex_units - * @param {ExUnitPrices} ex_unit_prices - * @returns {BigNum} - */ -declare export function calculate_ex_units_ceil_cost( - ex_units: ExUnits, - ex_unit_prices: ExUnitPrices -): BigNum; - -/** - * @param {Transaction} tx - * @param {ExUnitPrices} ex_unit_prices - * @returns {BigNum} + * @param {string} json + * @param {$Values< + typeof + PlutusDatumSchema>} schema + * @returns {PlutusData} */ -declare export function min_script_fee( - tx: Transaction, - ex_unit_prices: ExUnitPrices -): BigNum; +declare export function encode_json_str_to_plutus_datum( + json: string, + schema: $Values +): PlutusData; /** - * @param {number} total_ref_scripts_size - * @param {UnitInterval} ref_script_coins_per_byte - * @returns {BigNum} + * @param {PlutusData} datum + * @param {$Values< + typeof + PlutusDatumSchema>} schema + * @returns {string} */ -declare export function min_ref_script_fee( - total_ref_scripts_size: number, - ref_script_coins_per_byte: UnitInterval -): BigNum; +declare export function decode_plutus_datum_to_json_str( + datum: PlutusData, + schema: $Values +): string; /** + * @param {Uint8Array} bytes + * @returns {TransactionMetadatum} */ - -declare export var NativeScriptKind: {| - +ScriptPubkey: 0, // 0 - +ScriptAll: 1, // 1 - +ScriptAny: 2, // 2 - +ScriptNOfK: 3, // 3 - +TimelockStart: 4, // 4 - +TimelockExpiry: 5, // 5 -|}; +declare export function encode_arbitrary_bytes_as_metadatum( + bytes: Uint8Array +): TransactionMetadatum; /** + * @param {TransactionMetadatum} metadata + * @returns {Uint8Array} */ - -declare export var BlockEra: {| - +Byron: 0, // 0 - +Shelley: 1, // 1 - +Allegra: 2, // 2 - +Mary: 3, // 3 - +Alonzo: 4, // 4 - +Babbage: 5, // 5 - +Conway: 6, // 6 - +Unknown: 7, // 7 -|}; +declare export function decode_arbitrary_bytes_from_metadatum( + metadata: TransactionMetadatum +): Uint8Array; /** + * @param {string} json + * @param {$Values< + typeof + MetadataJsonSchema>} schema + * @returns {TransactionMetadatum} */ - -declare export var TransactionMetadatumKind: {| - +MetadataMap: 0, // 0 - +MetadataList: 1, // 1 - +Int: 2, // 2 - +Bytes: 3, // 3 - +Text: 4, // 4 -|}; +declare export function encode_json_str_to_metadatum( + json: string, + schema: $Values +): TransactionMetadatum; /** + * @param {TransactionMetadatum} metadatum + * @param {$Values< + typeof + MetadataJsonSchema>} schema + * @returns {string} */ - -declare export var VoteKind: {| - +No: 0, // 0 - +Yes: 1, // 1 - +Abstain: 2, // 2 -|}; +declare export function decode_metadatum_to_json_str( + metadatum: TransactionMetadatum, + schema: $Values +): string; /** */ -declare export var MIRKind: {| - +ToOtherPot: 0, // 0 - +ToStakeCredentials: 1, // 1 +declare export var NetworkIdKind: {| + +Testnet: 0, // 0 + +Mainnet: 1, // 1 |}; /** @@ -336,44 +290,26 @@ declare export var AddressKind: {| /** */ -declare export var GovernanceActionKind: {| - +ParameterChangeAction: 0, // 0 - +HardForkInitiationAction: 1, // 1 - +TreasuryWithdrawalsAction: 2, // 2 - +NoConfidenceAction: 3, // 3 - +UpdateCommitteeAction: 4, // 4 - +NewConstitutionAction: 5, // 5 - +InfoAction: 6, // 6 -|}; - -/** - */ - -declare export var MIRPot: {| - +Reserves: 0, // 0 - +Treasury: 1, // 1 +declare export var CborContainerType: {| + +Array: 0, // 0 + +Map: 1, // 1 |}; /** */ -declare export var NetworkIdKind: {| - +Testnet: 0, // 0 - +Mainnet: 1, // 1 +declare export var MIRKind: {| + +ToOtherPot: 0, // 0 + +ToStakeCredentials: 1, // 1 |}; /** - * Each new language uses a different namespace for hashing its script - * This is because you could have a language where the same bytes have different semantics - * So this avoids scripts in different languages mapping to the same hash - * Note that the enum value here is different than the enum value for deciding the cost model of a script + * Used to choosed the schema for a script JSON string */ -declare export var ScriptHashNamespace: {| - +NativeScript: 0, // 0 - +PlutusScript: 1, // 1 - +PlutusScriptV2: 2, // 2 - +PlutusScriptV3: 3, // 3 +declare export var ScriptSchema: {| + +Wallet: 0, // 0 + +Node: 1, // 1 |}; /** @@ -393,6 +329,34 @@ declare export var PlutusDatumSchema: {| +DetailedSchema: 1, // 1 |}; +/** + */ + +declare export var MIRPot: {| + +Reserves: 0, // 0 + +Treasury: 1, // 1 +|}; + +/** + */ + +declare export var TransactionMetadatumKind: {| + +MetadataMap: 0, // 0 + +MetadataList: 1, // 1 + +Int: 2, // 2 + +Bytes: 3, // 3 + +Text: 4, // 4 +|}; + +/** + */ + +declare export var RelayKind: {| + +SingleHostAddr: 0, // 0 + +SingleHostName: 1, // 1 + +MultiHostName: 2, // 2 +|}; + /** */ @@ -419,20 +383,23 @@ declare export var CertificateKind: {| /** */ -declare export var CoinSelectionStrategyCIP2: {| - +LargestFirst: 0, // 0 - +RandomImprove: 1, // 1 - +LargestFirstMultiAsset: 2, // 2 - +RandomImproveMultiAsset: 3, // 3 +declare export var GovernanceActionKind: {| + +ParameterChangeAction: 0, // 0 + +HardForkInitiationAction: 1, // 1 + +TreasuryWithdrawalsAction: 2, // 2 + +NoConfidenceAction: 3, // 3 + +UpdateCommitteeAction: 4, // 4 + +NewConstitutionAction: 5, // 5 + +InfoAction: 6, // 6 |}; /** */ -declare export var LanguageKind: {| - +PlutusV1: 0, // 0 - +PlutusV2: 1, // 1 - +PlutusV3: 2, // 2 +declare export var VoteKind: {| + +No: 0, // 0 + +Yes: 1, // 1 + +Abstain: 2, // 2 |}; /** @@ -446,71 +413,104 @@ declare export var DRepKind: {| |}; /** - * Used to choosed the schema for a script JSON string */ -declare export var ScriptSchema: {| - +Wallet: 0, // 0 - +Node: 1, // 1 +declare export var VoterKind: {| + +ConstitutionalCommitteeHotKeyHash: 0, // 0 + +ConstitutionalCommitteeHotScriptHash: 1, // 1 + +DRepKeyHash: 2, // 2 + +DRepScriptHash: 3, // 3 + +StakingPoolKeyHash: 4, // 4 |}; /** */ -declare export var RedeemerTagKind: {| - +Spend: 0, // 0 - +Mint: 1, // 1 - +Cert: 2, // 2 - +Reward: 3, // 3 - +Vote: 4, // 4 - +VotingProposal: 5, // 5 +declare export var CredKind: {| + +Key: 0, // 0 + +Script: 1, // 1 |}; /** */ -declare export var PlutusDataKind: {| - +ConstrPlutusData: 0, // 0 - +Map: 1, // 1 - +List: 2, // 2 - +Integer: 3, // 3 - +Bytes: 4, // 4 +declare export var BlockEra: {| + +Byron: 0, // 0 + +Shelley: 1, // 1 + +Allegra: 2, // 2 + +Mary: 3, // 3 + +Alonzo: 4, // 4 + +Babbage: 5, // 5 + +Conway: 6, // 6 + +Unknown: 7, // 7 |}; /** */ -declare export var VoterKind: {| - +ConstitutionalCommitteeHotKeyHash: 0, // 0 - +ConstitutionalCommitteeHotScriptHash: 1, // 1 - +DRepKeyHash: 2, // 2 - +DRepScriptHash: 3, // 3 - +StakingPoolKeyHash: 4, // 4 +declare export var LanguageKind: {| + +PlutusV1: 0, // 0 + +PlutusV2: 1, // 1 + +PlutusV3: 2, // 2 |}; /** */ -declare export var RelayKind: {| - +SingleHostAddr: 0, // 0 - +SingleHostName: 1, // 1 - +MultiHostName: 2, // 2 +declare export var NativeScriptKind: {| + +ScriptPubkey: 0, // 0 + +ScriptAll: 1, // 1 + +ScriptAny: 2, // 2 + +ScriptNOfK: 3, // 3 + +TimelockStart: 4, // 4 + +TimelockExpiry: 5, // 5 |}; /** */ -declare export var CborContainerType: {| - +Array: 0, // 0 +declare export var CoinSelectionStrategyCIP2: {| + +LargestFirst: 0, // 0 + +RandomImprove: 1, // 1 + +LargestFirstMultiAsset: 2, // 2 + +RandomImproveMultiAsset: 3, // 3 +|}; + +/** + */ + +declare export var PlutusDataKind: {| + +ConstrPlutusData: 0, // 0 +Map: 1, // 1 + +List: 2, // 2 + +Integer: 3, // 3 + +Bytes: 4, // 4 |}; /** */ -declare export var CredKind: {| - +Key: 0, // 0 - +Script: 1, // 1 +declare export var RedeemerTagKind: {| + +Spend: 0, // 0 + +Mint: 1, // 1 + +Cert: 2, // 2 + +Reward: 3, // 3 + +Vote: 4, // 4 + +VotingProposal: 5, // 5 +|}; + +/** + * Each new language uses a different namespace for hashing its script + * This is because you could have a language where the same bytes have different semantics + * So this avoids scripts in different languages mapping to the same hash + * Note that the enum value here is different than the enum value for deciding the cost model of a script + */ + +declare export var ScriptHashNamespace: {| + +NativeScript: 0, // 0 + +PlutusScript: 1, // 1 + +PlutusScriptV2: 2, // 2 + +PlutusScriptV3: 3, // 3 |}; /** @@ -4087,6 +4087,21 @@ declare export class FixedTransaction { */ raw_auxiliary_data(): Uint8Array | void; + /** + * @returns {TransactionHash} + */ + transaction_hash(): TransactionHash; + + /** + * @param {Vkeywitness} vkey_witness + */ + add_vkey_witness(vkey_witness: Vkeywitness): void; + + /** + * @param {BootstrapWitness} bootstrap_witness + */ + add_bootstrap_witness(bootstrap_witness: BootstrapWitness): void; + /** * @param {PrivateKey} private_key */ From f6cb29a388663e861a657ddfd453a3dc3820a007 Mon Sep 17 00:00:00 2001 From: lisicky Date: Mon, 9 Sep 2024 16:05:09 +0900 Subject: [PATCH 15/19] make FixedTxWitnessesSet public --- .../witnesses/fixed_tx_witnesses_set.rs | 20 +++++++++++++------ rust/src/protocol_types/witnesses/mod.rs | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs index 10f3e27e..8cea37bc 100644 --- a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs +++ b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs @@ -1,18 +1,26 @@ use crate::*; #[allow(dead_code)] + +/// A set of witnesses for a transaction. +/// Keeps original bytes to allow for safe roundtrip serialization. +/// That helps to avoid incorrect script data hash after adding a vkey or bootstrap witness. +/// You can add a vkey witness or a bootstrap witness to the set. +/// Or get TransactionWitnessSet to read fields. +#[wasm_bindgen] #[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct FixedTxWitnessesSet { pub(crate) raw_parts: TransactionWitnessSetRaw, pub(crate) tx_witnesses_set: TransactionWitnessSet, } +#[wasm_bindgen] impl FixedTxWitnessesSet { - pub(crate) fn tx_witnesses_set(&self) -> TransactionWitnessSet { + pub fn tx_witnesses_set(&self) -> TransactionWitnessSet { self.tx_witnesses_set.clone() } - pub(crate) fn add_vkey_witness(&mut self, vkey_witness: Vkeywitness) { + pub fn add_vkey_witness(&mut self, vkey_witness: Vkeywitness) { if self.tx_witnesses_set.vkeys.is_none() { self.tx_witnesses_set.vkeys = Some(Vkeywitnesses::new()); } @@ -22,7 +30,7 @@ impl FixedTxWitnessesSet { self.raw_parts.vkeys = None; } - pub(crate) fn add_bootstrap_witness(&mut self, bootstrap_witness: BootstrapWitness) { + pub fn add_bootstrap_witness(&mut self, bootstrap_witness: BootstrapWitness) { if self.tx_witnesses_set.bootstraps.is_none() { self.tx_witnesses_set.bootstraps = Some(BootstrapWitnesses::new()); } @@ -32,20 +40,20 @@ impl FixedTxWitnessesSet { self.raw_parts.bootstraps = None; } - pub(crate) fn to_bytes(&self) -> Vec { + pub fn to_bytes(&self) -> Vec { let mut buf = Serializer::new_vec(); self.serialize(&mut buf).unwrap(); buf.finalize() } #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))] - pub(crate) fn from_bytes(data: Vec) -> Result { + pub fn from_bytes(data: Vec) -> Result { let mut raw = Deserializer::from(std::io::Cursor::new(data)); Self::deserialize(&mut raw) } #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] - pub(crate) fn from_bytes(data: Vec) -> Result { + pub fn from_bytes(data: Vec) -> Result { let mut raw = Deserializer::from(std::io::Cursor::new(data)); Ok(Self::deserialize(&mut raw)?) } diff --git a/rust/src/protocol_types/witnesses/mod.rs b/rust/src/protocol_types/witnesses/mod.rs index 189a7bba..df19987b 100644 --- a/rust/src/protocol_types/witnesses/mod.rs +++ b/rust/src/protocol_types/witnesses/mod.rs @@ -19,5 +19,5 @@ mod transaction_witnesses_sets; pub use transaction_witnesses_sets::*; mod fixed_tx_witnesses_set; -pub(crate) use fixed_tx_witnesses_set::*; +pub use fixed_tx_witnesses_set::*; From 624bf3000ed6b83e21eccfa3b5b45195b1923449 Mon Sep 17 00:00:00 2001 From: lisicky Date: Mon, 9 Sep 2024 16:09:56 +0900 Subject: [PATCH 16/19] FixedTxWitnessesSet fix --- rust/src/protocol_types/fixed_tx.rs | 10 +++++----- .../protocol_types/witnesses/fixed_tx_witnesses_set.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/rust/src/protocol_types/fixed_tx.rs b/rust/src/protocol_types/fixed_tx.rs index 76ec61a6..cad72646 100644 --- a/rust/src/protocol_types/fixed_tx.rs +++ b/rust/src/protocol_types/fixed_tx.rs @@ -144,28 +144,28 @@ impl FixedTransaction { } pub fn add_vkey_witness(&mut self, vkey_witness: &Vkeywitness) { - self.witness_set.add_vkey_witness(vkey_witness.clone()); + self.witness_set.add_vkey_witness(vkey_witness); } pub fn add_bootstrap_witness(&mut self, bootstrap_witness: &BootstrapWitness) { - self.witness_set.add_bootstrap_witness(bootstrap_witness.clone()); + self.witness_set.add_bootstrap_witness(bootstrap_witness); } pub fn sign_and_add_vkey_signature(&mut self, private_key: &PrivateKey) -> Result<(), JsError> { let vkey_witness = make_vkey_witness(&self.tx_hash, private_key); - self.witness_set.add_vkey_witness(vkey_witness); + self.witness_set.add_vkey_witness(&vkey_witness); Ok(()) } pub fn sign_and_add_icarus_bootstrap_signature(&mut self, addr: &ByronAddress, private_key: &Bip32PrivateKey) -> Result<(), JsError> { let bootstrap_witness = make_icarus_bootstrap_witness(&self.tx_hash, addr, private_key); - self.witness_set.add_bootstrap_witness(bootstrap_witness); + self.witness_set.add_bootstrap_witness(&bootstrap_witness); Ok(()) } pub fn sign_and_add_daedalus_bootstrap_signature(&mut self, addr: &ByronAddress, private_key: &LegacyDaedalusPrivateKey) -> Result<(), JsError> { let bootstrap_witness = make_daedalus_bootstrap_witness(&self.tx_hash, addr, private_key); - self.witness_set.add_bootstrap_witness(bootstrap_witness); + self.witness_set.add_bootstrap_witness(&bootstrap_witness); Ok(()) } } diff --git a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs index 8cea37bc..7e8f0b84 100644 --- a/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs +++ b/rust/src/protocol_types/witnesses/fixed_tx_witnesses_set.rs @@ -9,7 +9,7 @@ use crate::*; /// Or get TransactionWitnessSet to read fields. #[wasm_bindgen] #[derive(Clone, Debug, Eq, PartialEq)] -pub(crate) struct FixedTxWitnessesSet { +pub struct FixedTxWitnessesSet { pub(crate) raw_parts: TransactionWitnessSetRaw, pub(crate) tx_witnesses_set: TransactionWitnessSet, } @@ -20,22 +20,22 @@ impl FixedTxWitnessesSet { self.tx_witnesses_set.clone() } - pub fn add_vkey_witness(&mut self, vkey_witness: Vkeywitness) { + pub fn add_vkey_witness(&mut self, vkey_witness: &Vkeywitness) { if self.tx_witnesses_set.vkeys.is_none() { self.tx_witnesses_set.vkeys = Some(Vkeywitnesses::new()); } if let Some(vkeys) = &mut self.tx_witnesses_set.vkeys { - vkeys.add(&vkey_witness); + vkeys.add(vkey_witness); } self.raw_parts.vkeys = None; } - pub fn add_bootstrap_witness(&mut self, bootstrap_witness: BootstrapWitness) { + pub fn add_bootstrap_witness(&mut self, bootstrap_witness: &BootstrapWitness) { if self.tx_witnesses_set.bootstraps.is_none() { self.tx_witnesses_set.bootstraps = Some(BootstrapWitnesses::new()); } if let Some(bootstraps) = &mut self.tx_witnesses_set.bootstraps { - bootstraps.add(&bootstrap_witness); + bootstraps.add(bootstrap_witness); } self.raw_parts.bootstraps = None; } From c60ca35533bae33028044e6835047980f85b53b2 Mon Sep 17 00:00:00 2001 From: lisicky Date: Mon, 9 Sep 2024 16:35:08 +0900 Subject: [PATCH 17/19] flow update --- rust/pkg/cardano_serialization_lib.js.flow | 444 +++++++++++---------- 1 file changed, 240 insertions(+), 204 deletions(-) diff --git a/rust/pkg/cardano_serialization_lib.js.flow b/rust/pkg/cardano_serialization_lib.js.flow index 5d7af25c..0057ac19 100644 --- a/rust/pkg/cardano_serialization_lib.js.flow +++ b/rust/pkg/cardano_serialization_lib.js.flow @@ -5,42 +5,6 @@ * @flow */ -/** - * @param {string} password - * @param {string} salt - * @param {string} nonce - * @param {string} data - * @returns {string} - */ -declare export function encrypt_with_password( - password: string, - salt: string, - nonce: string, - data: string -): string; - -/** - * @param {string} password - * @param {string} data - * @returns {string} - */ -declare export function decrypt_with_password( - password: string, - data: string -): string; - -/** - * @param {Address} address - * @param {TransactionUnspentOutputs} utxos - * @param {TransactionBuilderConfig} config - * @returns {TransactionBatchList} - */ -declare export function create_send_all( - address: Address, - utxos: TransactionUnspentOutputs, - config: TransactionBuilderConfig -): TransactionBatchList; - /** * @param {Transaction} tx * @param {LinearFee} linear_fee @@ -78,6 +42,106 @@ declare export function min_ref_script_fee( ref_script_coins_per_byte: UnitInterval ): BigNum; +/** + * @param {string} json + * @param {$Values< + typeof + PlutusDatumSchema>} schema + * @returns {PlutusData} + */ +declare export function encode_json_str_to_plutus_datum( + json: string, + schema: $Values +): PlutusData; + +/** + * @param {PlutusData} datum + * @param {$Values< + typeof + PlutusDatumSchema>} schema + * @returns {string} + */ +declare export function decode_plutus_datum_to_json_str( + datum: PlutusData, + schema: $Values +): string; + +/** + * @param {Uint8Array} bytes + * @returns {TransactionMetadatum} + */ +declare export function encode_arbitrary_bytes_as_metadatum( + bytes: Uint8Array +): TransactionMetadatum; + +/** + * @param {TransactionMetadatum} metadata + * @returns {Uint8Array} + */ +declare export function decode_arbitrary_bytes_from_metadatum( + metadata: TransactionMetadatum +): Uint8Array; + +/** + * @param {string} json + * @param {$Values< + typeof + MetadataJsonSchema>} schema + * @returns {TransactionMetadatum} + */ +declare export function encode_json_str_to_metadatum( + json: string, + schema: $Values +): TransactionMetadatum; + +/** + * @param {TransactionMetadatum} metadatum + * @param {$Values< + typeof + MetadataJsonSchema>} schema + * @returns {string} + */ +declare export function decode_metadatum_to_json_str( + metadatum: TransactionMetadatum, + schema: $Values +): string; + +/** + * @param {Address} address + * @param {TransactionUnspentOutputs} utxos + * @param {TransactionBuilderConfig} config + * @returns {TransactionBatchList} + */ +declare export function create_send_all( + address: Address, + utxos: TransactionUnspentOutputs, + config: TransactionBuilderConfig +): TransactionBatchList; + +/** + * @param {string} password + * @param {string} salt + * @param {string} nonce + * @param {string} data + * @returns {string} + */ +declare export function encrypt_with_password( + password: string, + salt: string, + nonce: string, + data: string +): string; + +/** + * @param {string} password + * @param {string} data + * @returns {string} + */ +declare export function decrypt_with_password( + password: string, + data: string +): string; + /** * @param {TransactionHash} tx_body_hash * @param {ByronAddress} addr @@ -204,103 +268,54 @@ declare export function encode_json_str_to_native_script( ): NativeScript; /** - * @param {string} json - * @param {$Values< - typeof - PlutusDatumSchema>} schema - * @returns {PlutusData} */ -declare export function encode_json_str_to_plutus_datum( - json: string, - schema: $Values -): PlutusData; -/** - * @param {PlutusData} datum - * @param {$Values< - typeof - PlutusDatumSchema>} schema - * @returns {string} - */ -declare export function decode_plutus_datum_to_json_str( - datum: PlutusData, - schema: $Values -): string; - -/** - * @param {Uint8Array} bytes - * @returns {TransactionMetadatum} - */ -declare export function encode_arbitrary_bytes_as_metadatum( - bytes: Uint8Array -): TransactionMetadatum; - -/** - * @param {TransactionMetadatum} metadata - * @returns {Uint8Array} - */ -declare export function decode_arbitrary_bytes_from_metadatum( - metadata: TransactionMetadatum -): Uint8Array; - -/** - * @param {string} json - * @param {$Values< - typeof - MetadataJsonSchema>} schema - * @returns {TransactionMetadatum} - */ -declare export function encode_json_str_to_metadatum( - json: string, - schema: $Values -): TransactionMetadatum; - -/** - * @param {TransactionMetadatum} metadatum - * @param {$Values< - typeof - MetadataJsonSchema>} schema - * @returns {string} - */ -declare export function decode_metadatum_to_json_str( - metadatum: TransactionMetadatum, - schema: $Values -): string; +declare export var TransactionMetadatumKind: {| + +MetadataMap: 0, // 0 + +MetadataList: 1, // 1 + +Int: 2, // 2 + +Bytes: 3, // 3 + +Text: 4, // 4 +|}; /** */ -declare export var NetworkIdKind: {| - +Testnet: 0, // 0 - +Mainnet: 1, // 1 +declare export var MetadataJsonSchema: {| + +NoConversions: 0, // 0 + +BasicConversions: 1, // 1 + +DetailedSchema: 2, // 2 |}; /** */ -declare export var AddressKind: {| - +Base: 0, // 0 - +Pointer: 1, // 1 - +Enterprise: 2, // 2 - +Reward: 3, // 3 - +Byron: 4, // 4 - +Malformed: 5, // 5 +declare export var PlutusDataKind: {| + +ConstrPlutusData: 0, // 0 + +Map: 1, // 1 + +List: 2, // 2 + +Integer: 3, // 3 + +Bytes: 4, // 4 |}; /** */ -declare export var CborContainerType: {| - +Array: 0, // 0 - +Map: 1, // 1 +declare export var VoteKind: {| + +No: 0, // 0 + +Yes: 1, // 1 + +Abstain: 2, // 2 |}; /** */ -declare export var MIRKind: {| - +ToOtherPot: 0, // 0 - +ToStakeCredentials: 1, // 1 +declare export var VoterKind: {| + +ConstitutionalCommitteeHotKeyHash: 0, // 0 + +ConstitutionalCommitteeHotScriptHash: 1, // 1 + +DRepKeyHash: 2, // 2 + +DRepScriptHash: 3, // 3 + +StakingPoolKeyHash: 4, // 4 |}; /** @@ -332,29 +347,61 @@ declare export var PlutusDatumSchema: {| /** */ -declare export var MIRPot: {| - +Reserves: 0, // 0 - +Treasury: 1, // 1 +declare export var CredKind: {| + +Key: 0, // 0 + +Script: 1, // 1 |}; /** */ -declare export var TransactionMetadatumKind: {| - +MetadataMap: 0, // 0 - +MetadataList: 1, // 1 - +Int: 2, // 2 - +Bytes: 3, // 3 - +Text: 4, // 4 +declare export var NetworkIdKind: {| + +Testnet: 0, // 0 + +Mainnet: 1, // 1 |}; /** */ -declare export var RelayKind: {| - +SingleHostAddr: 0, // 0 - +SingleHostName: 1, // 1 - +MultiHostName: 2, // 2 +declare export var MIRKind: {| + +ToOtherPot: 0, // 0 + +ToStakeCredentials: 1, // 1 +|}; + +/** + */ + +declare export var NativeScriptKind: {| + +ScriptPubkey: 0, // 0 + +ScriptAll: 1, // 1 + +ScriptAny: 2, // 2 + +ScriptNOfK: 3, // 3 + +TimelockStart: 4, // 4 + +TimelockExpiry: 5, // 5 +|}; + +/** + */ + +declare export var RedeemerTagKind: {| + +Spend: 0, // 0 + +Mint: 1, // 1 + +Cert: 2, // 2 + +Reward: 3, // 3 + +Vote: 4, // 4 + +VotingProposal: 5, // 5 +|}; + +/** + */ + +declare export var AddressKind: {| + +Base: 0, // 0 + +Pointer: 1, // 1 + +Enterprise: 2, // 2 + +Reward: 3, // 3 + +Byron: 4, // 4 + +Malformed: 5, // 5 |}; /** @@ -381,54 +428,34 @@ declare export var CertificateKind: {| |}; /** + * Each new language uses a different namespace for hashing its script + * This is because you could have a language where the same bytes have different semantics + * So this avoids scripts in different languages mapping to the same hash + * Note that the enum value here is different than the enum value for deciding the cost model of a script */ -declare export var GovernanceActionKind: {| - +ParameterChangeAction: 0, // 0 - +HardForkInitiationAction: 1, // 1 - +TreasuryWithdrawalsAction: 2, // 2 - +NoConfidenceAction: 3, // 3 - +UpdateCommitteeAction: 4, // 4 - +NewConstitutionAction: 5, // 5 - +InfoAction: 6, // 6 -|}; - -/** - */ - -declare export var VoteKind: {| - +No: 0, // 0 - +Yes: 1, // 1 - +Abstain: 2, // 2 -|}; - -/** - */ - -declare export var DRepKind: {| - +KeyHash: 0, // 0 - +ScriptHash: 1, // 1 - +AlwaysAbstain: 2, // 2 - +AlwaysNoConfidence: 3, // 3 +declare export var ScriptHashNamespace: {| + +NativeScript: 0, // 0 + +PlutusScript: 1, // 1 + +PlutusScriptV2: 2, // 2 + +PlutusScriptV3: 3, // 3 |}; /** */ -declare export var VoterKind: {| - +ConstitutionalCommitteeHotKeyHash: 0, // 0 - +ConstitutionalCommitteeHotScriptHash: 1, // 1 - +DRepKeyHash: 2, // 2 - +DRepScriptHash: 3, // 3 - +StakingPoolKeyHash: 4, // 4 +declare export var CborContainerType: {| + +Array: 0, // 0 + +Map: 1, // 1 |}; /** */ -declare export var CredKind: {| - +Key: 0, // 0 - +Script: 1, // 1 +declare export var RelayKind: {| + +SingleHostAddr: 0, // 0 + +SingleHostName: 1, // 1 + +MultiHostName: 2, // 2 |}; /** @@ -457,13 +484,14 @@ declare export var LanguageKind: {| /** */ -declare export var NativeScriptKind: {| - +ScriptPubkey: 0, // 0 - +ScriptAll: 1, // 1 - +ScriptAny: 2, // 2 - +ScriptNOfK: 3, // 3 - +TimelockStart: 4, // 4 - +TimelockExpiry: 5, // 5 +declare export var GovernanceActionKind: {| + +ParameterChangeAction: 0, // 0 + +HardForkInitiationAction: 1, // 1 + +TreasuryWithdrawalsAction: 2, // 2 + +NoConfidenceAction: 3, // 3 + +UpdateCommitteeAction: 4, // 4 + +NewConstitutionAction: 5, // 5 + +InfoAction: 6, // 6 |}; /** @@ -479,47 +507,19 @@ declare export var CoinSelectionStrategyCIP2: {| /** */ -declare export var PlutusDataKind: {| - +ConstrPlutusData: 0, // 0 - +Map: 1, // 1 - +List: 2, // 2 - +Integer: 3, // 3 - +Bytes: 4, // 4 -|}; - -/** - */ - -declare export var RedeemerTagKind: {| - +Spend: 0, // 0 - +Mint: 1, // 1 - +Cert: 2, // 2 - +Reward: 3, // 3 - +Vote: 4, // 4 - +VotingProposal: 5, // 5 -|}; - -/** - * Each new language uses a different namespace for hashing its script - * This is because you could have a language where the same bytes have different semantics - * So this avoids scripts in different languages mapping to the same hash - * Note that the enum value here is different than the enum value for deciding the cost model of a script - */ - -declare export var ScriptHashNamespace: {| - +NativeScript: 0, // 0 - +PlutusScript: 1, // 1 - +PlutusScriptV2: 2, // 2 - +PlutusScriptV3: 3, // 3 +declare export var MIRPot: {| + +Reserves: 0, // 0 + +Treasury: 1, // 1 |}; /** */ -declare export var MetadataJsonSchema: {| - +NoConversions: 0, // 0 - +BasicConversions: 1, // 1 - +DetailedSchema: 2, // 2 +declare export var DRepKind: {| + +KeyHash: 0, // 0 + +ScriptHash: 1, // 1 + +AlwaysAbstain: 2, // 2 + +AlwaysNoConfidence: 3, // 3 |}; /** @@ -4198,6 +4198,42 @@ declare export class FixedTransactionBody { */ original_bytes(): Uint8Array; } +/** + * A set of witnesses for a transaction. + * Keeps original bytes to allow for safe roundtrip serialization. + * That helps to avoid incorrect script data hash after adding a vkey or bootstrap witness. + * You can add a vkey witness or a bootstrap witness to the set. + * Or get TransactionWitnessSet to read fields. + */ +declare export class FixedTxWitnessesSet { + free(): void; + + /** + * @returns {TransactionWitnessSet} + */ + tx_witnesses_set(): TransactionWitnessSet; + + /** + * @param {Vkeywitness} vkey_witness + */ + add_vkey_witness(vkey_witness: Vkeywitness): void; + + /** + * @param {BootstrapWitness} bootstrap_witness + */ + add_bootstrap_witness(bootstrap_witness: BootstrapWitness): void; + + /** + * @returns {Uint8Array} + */ + to_bytes(): Uint8Array; + + /** + * @param {Uint8Array} data + * @returns {FixedTxWitnessesSet} + */ + static from_bytes(data: Uint8Array): FixedTxWitnessesSet; +} /** * Warning: This is experimental and may be removed in the future. */ From f0e709308d072d9b30a82deabca7c8d4fd8b5671 Mon Sep 17 00:00:00 2001 From: lisicky Date: Tue, 10 Sep 2024 20:16:41 +0900 Subject: [PATCH 18/19] add conditional feature for arbitrary-precision serde-json to avoid build conflicts --- rust/Cargo.toml | 5 +-- rust/src/protocol_types/plutus/plutus_data.rs | 35 +++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index b664eab5..04327701 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,7 +13,8 @@ exclude = [ ] [features] -default = [] +default = ["arbitrary-precision-json"] +arbitrary-precision-json = ["serde_json/arbitrary_precision"] #TODO: need to review the features and delete legacy ones. List is defined to avoid warnings. property-test-api = [] generic-serialization = [] @@ -32,7 +33,7 @@ bech32 = "0.7.2" hex = "0.4.0" cfg-if = "1" hashlink = "0.9.1" -serde_json = { version = "1.0.114", features = ["arbitrary_precision"] } +serde_json = { version = "1.0.114"} num-bigint = "0.4.0" num-integer = "0.1.45" # The default can't be compiled to wasm, so it's necessary to use either the 'nightly' diff --git a/rust/src/protocol_types/plutus/plutus_data.rs b/rust/src/protocol_types/plutus/plutus_data.rs index ad2cdc44..cd13256c 100644 --- a/rust/src/protocol_types/plutus/plutus_data.rs +++ b/rust/src/protocol_types/plutus/plutus_data.rs @@ -10,7 +10,6 @@ use cbor_event::{ }; use schemars::JsonSchema; -use serde_json::Number; #[wasm_bindgen] #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)] @@ -611,13 +610,27 @@ pub fn encode_json_value_to_plutus_datum( schema: PlutusDatumSchema, ) -> Result { use serde_json::Value; - fn encode_number(x: Number) -> Result { + + #[cfg(feature = "arbitrary-precision-json")] + fn encode_number(x: serde_json::Number) -> Result { if let Ok(big_int) = BigInt::from_str(x.as_str()) { Ok(PlutusData::new_integer(&big_int)) } else { Err(JsError::from_str(&format!("Expected an integer value but got \"{}\"", x))) } } + + #[cfg(not(feature = "arbitrary-precision-json"))] + fn encode_number(x: serde_json::Number) -> Result { + if let Some(x) = x.as_u64() { + Ok(PlutusData::new_integer(&BigInt::from(x))) + } else if let Some(x) = x.as_i64() { + Ok(PlutusData::new_integer(&BigInt::from(x))) + } else { + Err(JsError::from_str("floats not allowed in plutus datums")) + } + } + fn encode_string( s: &str, schema: PlutusDatumSchema, @@ -829,7 +842,7 @@ pub fn decode_plutus_datum_to_json_value( }, PlutusDataEnum::Integer(bigint) => ( Some("int"), - Value::Number(Number::from_string_unchecked(bigint.to_str())) + bigint_to_serde_value(bigint)? ), PlutusDataEnum::Bytes(bytes) => (Some("bytes"), Value::from(match schema { PlutusDatumSchema::BasicConversions => { @@ -851,3 +864,19 @@ pub fn decode_plutus_datum_to_json_value( Ok(Value::from(wrapper)) } } + +#[cfg(not(feature = "arbitrary-precision-json"))] +fn bigint_to_serde_value(bigint: &BigInt) -> Result { + bigint + .as_int() + .as_ref() + .map(|int| if int.0 >= 0 { serde_json::Value::from(int.0 as u64) } else {serde_json:: Value::from(int.0 as i64) }) + .ok_or_else(|| JsError::from_str(&format!("Integer {} too big for our JSON support", bigint.to_str()))) +} + +#[cfg(feature = "arbitrary-precision-json")] +fn bigint_to_serde_value(bigint: &BigInt) -> Result { + use serde_json::Number; + Ok(serde_json::Value::Number(Number::from_string_unchecked(bigint.to_str()))) +} + From 85398edc89ce2d4c17e912cf11b1ced60c04cd0e Mon Sep 17 00:00:00 2001 From: lisicky Date: Tue, 10 Sep 2024 20:27:12 +0900 Subject: [PATCH 19/19] add test --- rust/src/tests/general.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rust/src/tests/general.rs b/rust/src/tests/general.rs index 963eeedd..29eb5a11 100644 --- a/rust/src/tests/general.rs +++ b/rust/src/tests/general.rs @@ -851,4 +851,19 @@ fn plutus_map_keys_duplication_test() { assert_eq!(map_from_bytes.total_len(), 3); assert_eq!(map, map_from_bytes) +} + +#[test] +fn too_big_plutus_int_to_json() { + let too_big_int = BigInt::from_str("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999").unwrap(); + let plutus_data = PlutusData::new_integer(&too_big_int); + let json = plutus_data.to_json(PlutusDatumSchema::DetailedSchema); + #[cfg(feature = "arbitrary-precision-json")] + { + assert!(json.is_ok()); + } + #[cfg(not(feature = "arbitrary-precision-json"))] + { + assert!(json.is_err()); + } } \ No newline at end of file