fix(txbuilder): sign transactions using Conway era (#531)
This commit is contained in:
parent
a29a6cf50f
commit
3adc16b798
5 changed files with 45 additions and 21 deletions
|
|
@ -6,8 +6,8 @@ use pallas_primitives::{
|
||||||
conway::{
|
conway::{
|
||||||
DatumOption, ExUnits as PallasExUnits, NativeScript, NetworkId, NonZeroInt, PlutusData,
|
DatumOption, ExUnits as PallasExUnits, NativeScript, NetworkId, NonZeroInt, PlutusData,
|
||||||
PlutusScript, PostAlonzoTransactionOutput, PseudoScript as PallasScript,
|
PlutusScript, PostAlonzoTransactionOutput, PseudoScript as PallasScript,
|
||||||
PseudoTransactionOutput, Redeemer, RedeemerTag, TransactionBody, TransactionInput,
|
PseudoTransactionOutput, Redeemer, RedeemerTag, TransactionBody, TransactionInput, Tx,
|
||||||
Tx as BabbageTx, Value, WitnessSet,
|
Value, WitnessSet,
|
||||||
},
|
},
|
||||||
Fragment, NonEmptyKeyValuePairs, NonEmptySet, PositiveCoin,
|
Fragment, NonEmptyKeyValuePairs, NonEmptySet, PositiveCoin,
|
||||||
};
|
};
|
||||||
|
|
@ -25,15 +25,15 @@ use crate::{
|
||||||
TxBuilderError,
|
TxBuilderError,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait BuildBabbage {
|
pub trait BuildConway {
|
||||||
fn build_babbage_raw(self) -> Result<BuiltTransaction, TxBuilderError>;
|
fn build_conway_raw(self) -> Result<BuiltTransaction, TxBuilderError>;
|
||||||
|
|
||||||
// fn build_babbage(staging_tx: StagingTransaction, resolver: (), params: ()) ->
|
// fn build_babbage(staging_tx: StagingTransaction, resolver: (), params: ()) ->
|
||||||
// Result<BuiltTransaction, TxBuilderError>;
|
// Result<BuiltTransaction, TxBuilderError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuildBabbage for StagingTransaction {
|
impl BuildConway for StagingTransaction {
|
||||||
fn build_babbage_raw(self) -> Result<BuiltTransaction, TxBuilderError> {
|
fn build_conway_raw(self) -> Result<BuiltTransaction, TxBuilderError> {
|
||||||
let mut inputs = self
|
let mut inputs = self
|
||||||
.inputs
|
.inputs
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
|
|
@ -220,15 +220,21 @@ impl BuildBabbage for StagingTransaction {
|
||||||
);
|
);
|
||||||
|
|
||||||
let script_data_hash = self.language_view.map(|language_view| {
|
let script_data_hash = self.language_view.map(|language_view| {
|
||||||
scriptdata::ScriptData {
|
let dta = scriptdata::ScriptData {
|
||||||
redeemers: witness_set_redeemers.clone(),
|
redeemers: witness_set_redeemers.clone(),
|
||||||
datums: Some(plutus_data.clone()),
|
datums: if !plutus_data.is_empty() {
|
||||||
|
Some(plutus_data.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
language_view,
|
language_view,
|
||||||
}
|
};
|
||||||
.hash()
|
|
||||||
|
dbg!(&dta);
|
||||||
|
dta.hash()
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut pallas_tx = BabbageTx {
|
let mut pallas_tx = Tx {
|
||||||
transaction_body: TransactionBody {
|
transaction_body: TransactionBody {
|
||||||
inputs: pallas_primitives::Set::from(inputs),
|
inputs: pallas_primitives::Set::from(inputs),
|
||||||
outputs,
|
outputs,
|
||||||
|
|
@ -274,7 +280,7 @@ impl BuildBabbage for StagingTransaction {
|
||||||
|
|
||||||
Ok(BuiltTransaction {
|
Ok(BuiltTransaction {
|
||||||
version: self.version,
|
version: self.version,
|
||||||
era: BuilderEra::Babbage,
|
era: BuilderEra::Conway,
|
||||||
status: TransactionStatus::Built,
|
status: TransactionStatus::Built,
|
||||||
tx_hash: Bytes32(*pallas_tx.transaction_body.compute_hash()),
|
tx_hash: Bytes32(*pallas_tx.transaction_body.compute_hash()),
|
||||||
tx_bytes: Bytes(pallas_tx.encode_fragment().unwrap()),
|
tx_bytes: Bytes(pallas_tx.encode_fragment().unwrap()),
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
mod babbage;
|
mod conway;
|
||||||
mod scriptdata;
|
mod scriptdata;
|
||||||
mod transaction;
|
mod transaction;
|
||||||
|
|
||||||
pub use babbage::BuildBabbage;
|
pub use conway::BuildConway;
|
||||||
pub use transaction::model::{
|
pub use transaction::model::{
|
||||||
BuiltTransaction, ExUnits, Input, Output, ScriptKind, StagingTransaction,
|
BuiltTransaction, ExUnits, Input, Output, ScriptKind, StagingTransaction,
|
||||||
};
|
};
|
||||||
|
|
@ -34,4 +34,7 @@ pub enum TxBuilderError {
|
||||||
/// Asset name is too long, it must be 32 bytes or less
|
/// Asset name is too long, it must be 32 bytes or less
|
||||||
#[error("Asset name must be 32 bytes or less")]
|
#[error("Asset name must be 32 bytes or less")]
|
||||||
AssetNameTooLong,
|
AssetNameTooLong,
|
||||||
|
/// Unsupported era
|
||||||
|
#[error("Unsupported era")]
|
||||||
|
UnsupportedEra,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ impl<C> Encode<C> for LanguageView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct ScriptData {
|
pub struct ScriptData {
|
||||||
pub redeemers: Redeemers,
|
pub redeemers: Redeemers,
|
||||||
pub datums: Option<Vec<PlutusData>>,
|
pub datums: Option<Vec<PlutusData>>,
|
||||||
|
|
@ -112,6 +113,10 @@ mod tests {
|
||||||
hex::decode(include_str!("../../test_data/conway2.tx")).unwrap(),
|
hex::decode(include_str!("../../test_data/conway2.tx")).unwrap(),
|
||||||
LanguageView(0, COST_MODEL_PLUTUS_V1.clone()),
|
LanguageView(0, COST_MODEL_PLUTUS_V1.clone()),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
hex::decode(include_str!("../../test_data/hydra-init.tx")).unwrap(),
|
||||||
|
LanguageView(1, COST_MODEL_PLUTUS_V2.clone()),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use pallas_crypto::{
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
key::ed25519,
|
key::ed25519,
|
||||||
};
|
};
|
||||||
use pallas_primitives::{babbage, Fragment};
|
use pallas_primitives::{babbage, conway, Fragment, NonEmptySet};
|
||||||
use pallas_wallet::PrivateKey;
|
use pallas_wallet::PrivateKey;
|
||||||
|
|
||||||
use std::{collections::HashMap, ops::Deref};
|
use std::{collections::HashMap, ops::Deref};
|
||||||
|
|
@ -599,6 +599,7 @@ impl From<PallasAddress> for Address {
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum BuilderEra {
|
pub enum BuilderEra {
|
||||||
Babbage,
|
Babbage,
|
||||||
|
Conway,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
||||||
|
|
@ -626,7 +627,7 @@ impl BuiltTransaction {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
match self.era {
|
match self.era {
|
||||||
BuilderEra::Babbage => {
|
BuilderEra::Conway => {
|
||||||
let mut new_sigs = self.signatures.unwrap_or_default();
|
let mut new_sigs = self.signatures.unwrap_or_default();
|
||||||
|
|
||||||
new_sigs.insert(Bytes32(pubkey), Bytes64(signature));
|
new_sigs.insert(Bytes32(pubkey), Bytes64(signature));
|
||||||
|
|
@ -634,20 +635,26 @@ impl BuiltTransaction {
|
||||||
self.signatures = Some(new_sigs);
|
self.signatures = Some(new_sigs);
|
||||||
|
|
||||||
// TODO: chance for serialisation round trip issues?
|
// TODO: chance for serialisation round trip issues?
|
||||||
let mut tx = babbage::Tx::decode_fragment(&self.tx_bytes.0)
|
let mut tx = conway::Tx::decode_fragment(&self.tx_bytes.0)
|
||||||
.map_err(|_| TxBuilderError::CorruptedTxBytes)?;
|
.map_err(|_| TxBuilderError::CorruptedTxBytes)?;
|
||||||
|
|
||||||
let mut vkey_witnesses = tx.transaction_witness_set.vkeywitness.unwrap_or_default();
|
let mut vkey_witnesses = tx
|
||||||
|
.transaction_witness_set
|
||||||
|
.vkeywitness
|
||||||
|
.map(|x| x.to_vec())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
vkey_witnesses.push(babbage::VKeyWitness {
|
vkey_witnesses.push(babbage::VKeyWitness {
|
||||||
vkey: Vec::from(pubkey.as_ref()).into(),
|
vkey: Vec::from(pubkey.as_ref()).into(),
|
||||||
signature: Vec::from(signature.as_ref()).into(),
|
signature: Vec::from(signature.as_ref()).into(),
|
||||||
});
|
});
|
||||||
|
|
||||||
tx.transaction_witness_set.vkeywitness = Some(vkey_witnesses);
|
tx.transaction_witness_set.vkeywitness =
|
||||||
|
Some(NonEmptySet::from_vec(vkey_witnesses).unwrap());
|
||||||
|
|
||||||
self.tx_bytes = tx.encode_fragment().unwrap().into();
|
self.tx_bytes = tx.encode_fragment().unwrap().into();
|
||||||
}
|
}
|
||||||
|
_ => return Err(TxBuilderError::UnsupportedEra),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
|
@ -659,7 +666,7 @@ impl BuiltTransaction {
|
||||||
signature: [u8; 64],
|
signature: [u8; 64],
|
||||||
) -> Result<Self, TxBuilderError> {
|
) -> Result<Self, TxBuilderError> {
|
||||||
match self.era {
|
match self.era {
|
||||||
BuilderEra::Babbage => {
|
BuilderEra::Conway => {
|
||||||
let mut new_sigs = self.signatures.unwrap_or_default();
|
let mut new_sigs = self.signatures.unwrap_or_default();
|
||||||
|
|
||||||
new_sigs.insert(
|
new_sigs.insert(
|
||||||
|
|
@ -689,6 +696,7 @@ impl BuiltTransaction {
|
||||||
|
|
||||||
self.tx_bytes = tx.encode_fragment().unwrap().into();
|
self.tx_bytes = tx.encode_fragment().unwrap().into();
|
||||||
}
|
}
|
||||||
|
_ => return Err(TxBuilderError::UnsupportedEra),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
|
@ -696,7 +704,7 @@ impl BuiltTransaction {
|
||||||
|
|
||||||
pub fn remove_signature(mut self, pub_key: ed25519::PublicKey) -> Result<Self, TxBuilderError> {
|
pub fn remove_signature(mut self, pub_key: ed25519::PublicKey) -> Result<Self, TxBuilderError> {
|
||||||
match self.era {
|
match self.era {
|
||||||
BuilderEra::Babbage => {
|
BuilderEra::Conway => {
|
||||||
let mut new_sigs = self.signatures.unwrap_or_default();
|
let mut new_sigs = self.signatures.unwrap_or_default();
|
||||||
|
|
||||||
let pk = Bytes32(
|
let pk = Bytes32(
|
||||||
|
|
@ -722,6 +730,7 @@ impl BuiltTransaction {
|
||||||
|
|
||||||
self.tx_bytes = tx.encode_fragment().unwrap().into();
|
self.tx_bytes = tx.encode_fragment().unwrap().into();
|
||||||
}
|
}
|
||||||
|
_ => return Err(TxBuilderError::UnsupportedEra),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
|
|
||||||
1
test_data/hydra-init.tx
Normal file
1
test_data/hydra-init.tx
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue