diff --git a/data_structures/src/transaction.rs b/data_structures/src/transaction.rs index 31750b14e..1a9264371 100644 --- a/data_structures/src/transaction.rs +++ b/data_structures/src/transaction.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; +use crate::stack::{Item, MyValue, ScriptError}; use crate::{ chain::{ Block, Bn256PublicKey, DataRequestOutput, Epoch, Hash, Hashable, Input, KeyedSignature, @@ -199,13 +200,22 @@ pub fn mint(tx: &Transaction) -> Option<&MintTransaction> { } pub fn vtt_signature_to_witness(ks: &KeyedSignature) -> Vec { - // TODO: it would be nice to encode KeyedSignature as a script - // This way vtt.witness is always a valid script - ks.to_pb_bytes().unwrap() + let script = vec![Item::Value(MyValue::from_signature(ks))]; + + crate::stack::encode(&script).unwrap() } -pub fn vtt_witness_to_signature(witness: &[u8]) -> KeyedSignature { - KeyedSignature::from_pb_bytes(witness).unwrap() +pub fn vtt_witness_to_signature(witness: &[u8]) -> Result { + let script = crate::stack::decode(witness)?; + + if script.len() != 1 { + return Err(ScriptError::InvalidSignature); + } + + match &script[0] { + Item::Value(value) => value.to_signature(), + _ => Err(ScriptError::InvalidSignature), + } } #[derive(Debug, Default, Eq, PartialEq, Clone, Serialize, Deserialize, ProtobufConvert, Hash)] diff --git a/src/cli/node/json_rpc_client.rs b/src/cli/node/json_rpc_client.rs index 3e504ba76..93b898deb 100644 --- a/src/cli/node/json_rpc_client.rs +++ b/src/cli/node/json_rpc_client.rs @@ -904,10 +904,9 @@ pub fn sign_tx( match tx { Transaction::ValueTransfer(ref mut vtt) => { - let signature_bytes = signature.to_pb_bytes()?; - // TODO: this only works if the witness field represents a script - // It could also represent a signature in the case of normal value transfer - // transactions. It would be nice to also support signing normal transactions here + let signature_bytes = MyValue::from_signature(&signature); + // This also works with normal transactions, because the signature is encoded as a + // script with one element. let mut script = witnet_data_structures::stack::decode(&vtt.witness[input_index])?; println!( @@ -915,10 +914,7 @@ pub fn sign_tx( witnet_data_structures::stack::parser::script_to_string(&script) ); - script.insert( - signature_position_in_witness, - Item::Value(MyValue::Bytes(signature_bytes)), - ); + script.insert(signature_position_in_witness, Item::Value(signature_bytes)); println!( "-----------------------\nNew witness:\n-----------------------\n{}", diff --git a/validations/src/validations.rs b/validations/src/validations.rs index 25ea0eef3..81a8e6186 100644 --- a/validations/src/validations.rs +++ b/validations/src/validations.rs @@ -1243,7 +1243,7 @@ pub fn validate_transaction_signatures( if input.redeem_script.is_empty() { // Validate that public key hash of the pointed output matches public // key in the provided signature - let keyed_signature = vtt_witness_to_signature(witness); + let keyed_signature = vtt_witness_to_signature(witness)?; validate_pkh_signature(input, &keyed_signature, utxo_set).map_err(fte)?; // Validate the actual signature