Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(wallet): invalid metadata sig when creating code template utxo #4975

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions applications/tari_console_wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tari_app_grpc = { path = "../tari_app_grpc" }
tari_shutdown = { path = "../../infrastructure/shutdown" }
tari_key_manager = { path = "../../base_layer/key_manager" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.10" }
tari_script = { path = "../../infrastructure/tari_script" }

# Uncomment for tokio tracing via tokio-console (needs "tracing" featurs)
#console-subscriber = "0.1.3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ use tari_core::{
},
},
};
use tari_script::script;
use tari_utilities::{hex::Hex, ByteArray};
use tari_wallet::{
connectivity_service::{OnlineStatus, WalletConnectivityInterface},
Expand Down Expand Up @@ -929,7 +930,7 @@ impl wallet_server::Wallet for WalletGrpcServer {
let fee_per_gram = message.fee_per_gram;

let message = format!("Template registration {}", template_registration.template_name);
let output = output_manager
let mut output = output_manager
.create_output_with_features(1 * T, OutputFeatures {
output_type: OutputType::CodeTemplateRegistration,
sidechain_feature: Some(SideChainFeature::TemplateRegistration(template_registration)),
Expand All @@ -938,6 +939,8 @@ impl wallet_server::Wallet for WalletGrpcServer {
.await
.map_err(|e| Status::internal(e.to_string()))?;

output = output.with_script(script![Nop]);

let (tx_id, transaction) = output_manager
.create_send_to_self_with_output(vec![output], fee_per_gram.into(), UtxoSelectionCriteria::default())
.await
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,8 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use derivative::Derivative;
use tari_common_types::types::{
BlindingFactor,
ComAndPubSignature,
Commitment,
CommitmentFactory,
PrivateKey,
PublicKey,
};
use tari_crypto::commitment::HomomorphicCommitmentFactory;
use tari_common_types::types::{BlindingFactor, ComAndPubSignature, PrivateKey, PublicKey};
use tari_crypto::keys::PublicKey as PublicKeyTrait;
use tari_script::{ExecutionStack, TariScript};

use crate::{
Expand All @@ -45,7 +38,6 @@ use crate::{
UnblindedOutput,
},
transaction_protocol::RewindData,
CryptoFactories,
},
};

Expand Down Expand Up @@ -94,56 +86,69 @@ impl UnblindedOutputBuilder {
self.sender_offset_public_key = Some(sender_offset_public_key);
}

pub fn sign_as_receiver(&mut self, ephemeral_pubkey: PublicKey) -> Result<(), TransactionError> {
let sender_offset_public_key = self
.sender_offset_public_key
.as_ref()
.ok_or(TransactionError::MissingTransactionInputData)?;
let metadata_partial = TransactionOutput::create_receiver_partial_metadata_signature(
TransactionOutputVersion::get_current_version(),
self.value,
&self.spending_key,
self.script
.as_ref()
.ok_or_else(|| TransactionError::ValidationError("script must be set".to_string()))?,
&self.features,
sender_offset_public_key,
&ephemeral_pubkey,
&self.covenant,
&self.encrypted_value,
self.minimum_value_promise,
)?;
self.metadata_signature = Some(metadata_partial);
self.metadata_signed_by_receiver = true;
Ok(())
pub fn with_features(mut self, features: OutputFeatures) -> Self {
self.features = features;
self
}

pub fn with_script(mut self, script: TariScript) -> Self {
self.script = Some(script);
self
}

pub fn with_input_data(mut self, input_data: ExecutionStack) -> Self {
self.input_data = Some(input_data);
self
}

pub fn with_rewind_data(mut self, rewind_data: RewindData) -> Self {
self.rewind_data = Some(rewind_data);
self
}

pub fn with_script_private_key(mut self, script_private_key: PrivateKey) -> Self {
self.script_private_key = Some(script_private_key);
self
}

pub fn value(&self) -> MicroTari {
self.value
}

pub fn features(&self) -> &OutputFeatures {
&self.features
}

pub fn script(&self) -> Option<&TariScript> {
self.script.as_ref()
}

pub fn covenant(&self) -> &Covenant {
&self.covenant
}

pub fn sign_as_sender(
pub fn sign_as_sender_and_receiver(
&mut self,
sender_offset_private_key: &PrivateKey,
ephemeral_private_key: &PrivateKey,
) -> Result<(), TransactionError> {
let commitment = CommitmentFactory::default().commit_value(&self.spending_key, self.value.as_u64());
let def_commitment = Commitment::default();
let ephemeral_commitment = match self.metadata_signature.as_ref().map(|v| v.ephemeral_commitment()) {
Some(v) => v,
None => &def_commitment,
};
let metadata_sig = TransactionOutput::create_sender_partial_metadata_signature(
let script = self
.script
.as_ref()
.ok_or_else(|| TransactionError::ValidationError("Cannot sign metadata without a script".to_string()))?;
let metadata_signature = TransactionOutput::create_metadata_signature(
TransactionOutputVersion::get_current_version(),
&commitment,
ephemeral_commitment,
self.script
.as_ref()
.ok_or_else(|| TransactionError::ValidationError("script must be set".to_string()))?,
self.value,
&self.spending_key,
script,
&self.features,
sender_offset_private_key,
Some(ephemeral_private_key),
&self.covenant,
&self.encrypted_value,
self.minimum_value_promise,
)?;
self.metadata_signature = Some(metadata_sig);
self.sender_offset_public_key = Some(PublicKey::from_secret_key(sender_offset_private_key));
self.metadata_signature = Some(metadata_signature);
self.metadata_signed_by_receiver = true;
self.metadata_signed_by_sender = true;
Ok(())
}
Expand Down Expand Up @@ -180,53 +185,6 @@ impl UnblindedOutputBuilder {
);
Ok(ub)
}

pub fn with_features(mut self, features: OutputFeatures) -> Self {
self.features = features;
self
}

pub fn with_script(mut self, script: TariScript) -> Self {
self.script = Some(script);
self
}

pub fn with_input_data(mut self, input_data: ExecutionStack) -> Self {
self.input_data = Some(input_data);
self
}

pub fn with_rewind_data(mut self, rewind_data: RewindData) -> Self {
self.rewind_data = Some(rewind_data);
self
}

pub fn with_script_private_key(mut self, script_private_key: PrivateKey) -> Self {
self.script_private_key = Some(script_private_key);
self
}

pub fn value(&self) -> MicroTari {
self.value
}

pub fn features(&self) -> &OutputFeatures {
&self.features
}

pub fn script(&self) -> Option<&TariScript> {
self.script.as_ref()
}

pub fn covenant(&self) -> &Covenant {
&self.covenant
}

pub fn generate_commitment(&self, factories: &CryptoFactories) -> Commitment {
factories
.commitment
.commit_value(&self.spending_key, self.value.as_u64())
}
}

#[cfg(test)]
Expand All @@ -237,19 +195,12 @@ mod test {

#[test]
fn test_try_build() {
let mut uob = UnblindedOutputBuilder::new(100.into(), RistrettoSecretKey::default());
assert!(uob.sign_as_receiver(PublicKey::default(),).is_err());
assert!(uob
.sign_as_sender(&PrivateKey::default(), &PrivateKey::default())
.is_err());
let uob = UnblindedOutputBuilder::new(100.into(), RistrettoSecretKey::default());
let mut uob = uob.with_script(TariScript::new(vec![]));
assert!(uob.clone().try_build().is_err());
uob.with_sender_offset_public_key(PublicKey::default());
assert!(uob.sign_as_receiver(PublicKey::default()).is_ok());
assert!(uob.sign_as_sender_and_receiver(&PrivateKey::default()).is_ok());
assert!(uob.clone().try_build().is_err());
assert!(uob
.sign_as_sender(&PrivateKey::default(), &PrivateKey::default())
.is_ok());
let uob = uob.with_input_data(ExecutionStack::new(vec![]));
let uob = uob.with_script_private_key(RistrettoSecretKey::default());
let uob = uob.with_features(OutputFeatures::default());
Expand Down
8 changes: 1 addition & 7 deletions base_layer/wallet/src/output_manager_service/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,13 +1187,7 @@ where
let mut db_outputs = vec![];
for mut unblinded_output in outputs {
let sender_offset_private_key = PrivateKey::random(&mut OsRng);
let sender_offset_public_key = PublicKey::from_secret_key(&sender_offset_private_key);
unblinded_output.with_sender_offset_public_key(sender_offset_public_key);
let ephemeral_private_key = PrivateKey::random(&mut OsRng);
let ephemeral_pub_key = PublicKey::from_secret_key(&ephemeral_private_key);

unblinded_output.sign_as_receiver(ephemeral_pub_key)?;
unblinded_output.sign_as_sender(&sender_offset_private_key, &ephemeral_private_key)?;
unblinded_output.sign_as_sender_and_receiver(&sender_offset_private_key)?;

let ub = unblinded_output.try_build()?;
builder
Expand Down