From 3e99d3fb3dabd3ed65c6e1addd4c543ca4fe088b Mon Sep 17 00:00:00 2001 From: Tomasz Polaczyk Date: Wed, 17 Aug 2022 17:10:06 +0200 Subject: [PATCH] feat: encode legacy signatures as script with one element --- data_structures/src/transaction.rs | 20 +++++++++++++++----- src/cli/node/json_rpc_client.rs | 9 ++++----- validations/src/validations.rs | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/data_structures/src/transaction.rs b/data_structures/src/transaction.rs index 31750b14e2..1a92643712 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 3e504ba76c..4a1c90e1f9 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!( @@ -917,7 +916,7 @@ pub fn sign_tx( script.insert( signature_position_in_witness, - Item::Value(MyValue::Bytes(signature_bytes)), + Item::Value(signature_bytes), ); println!( diff --git a/validations/src/validations.rs b/validations/src/validations.rs index 25ea0eef34..81a8e61868 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