Skip to content

Commit

Permalink
fix(tari-script): use tari script encoding for execution stack serde …
Browse files Browse the repository at this point in the history
…de/serialization
  • Loading branch information
sdbondi committed Oct 10, 2022
1 parent e59be99 commit b6feb5f
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ impl TryFrom<TransactionInput> for grpc::TransactionInput {
script: input
.script()
.map_err(|_| "Non-compact Transaction input should contain script".to_string())?
.as_bytes(),
input_data: input.input_data.as_bytes(),
.to_bytes(),
input_data: input.input_data.to_bytes(),
script_signature,
sender_offset_public_key: input
.sender_offset_public_key()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl From<TransactionOutput> for grpc::TransactionOutput {
features: Some(output.features.into()),
commitment: Vec::from(output.commitment.as_bytes()),
range_proof: Vec::from(output.proof.as_bytes()),
script: output.script.as_bytes(),
script: output.script.to_bytes(),
sender_offset_public_key: output.sender_offset_public_key.as_bytes().to_vec(),
metadata_signature: Some(grpc::ComSignature {
public_nonce_commitment: Vec::from(output.metadata_signature.public_nonce().as_bytes()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ impl From<UnblindedOutput> for grpc::UnblindedOutput {
value: u64::from(output.value),
spending_key: output.spending_key.as_bytes().to_vec(),
features: Some(output.features.into()),
script: output.script.as_bytes(),
input_data: output.input_data.as_bytes(),
script: output.script.to_bytes(),
input_data: output.input_data.to_bytes(),
script_private_key: output.script_private_key.as_bytes().to_vec(),
sender_offset_public_key: output.sender_offset_public_key.as_bytes().to_vec(),
metadata_signature: Some(grpc::ComSignature {
Expand Down
4 changes: 2 additions & 2 deletions base_layer/core/src/consensus/consensus_encoding/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSi

impl ConsensusEncoding for TariScript {
fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
self.as_bytes().consensus_encode(writer)
self.to_bytes().consensus_encode(writer)
}
}

Expand All @@ -54,7 +54,7 @@ impl ConsensusDecoding for TariScript {

impl ConsensusEncoding for ExecutionStack {
fn consensus_encode<W: io::Write>(&self, writer: &mut W) -> Result<(), io::Error> {
self.as_bytes().consensus_encode(writer)
self.to_bytes().consensus_encode(writer)
}
}

Expand Down
8 changes: 4 additions & 4 deletions base_layer/core/src/proto/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ impl TryFrom<TransactionInput> for proto::types::TransactionInput {
if input.is_compact() {
let output_hash = input.output_hash();
Ok(Self {
input_data: input.input_data.as_bytes(),
input_data: input.input_data.to_bytes(),
script_signature: Some(input.script_signature.into()),
output_hash: output_hash.to_vec(),
..Default::default()
Expand All @@ -192,8 +192,8 @@ impl TryFrom<TransactionInput> for proto::types::TransactionInput {
script: input
.script()
.map_err(|_| "Non-compact Transaction input should contain script".to_string())?
.as_bytes(),
input_data: input.input_data.as_bytes(),
.to_bytes(),
input_data: input.input_data.to_bytes(),
script_signature: Some(input.script_signature.clone().into()),
sender_offset_public_key: input
.sender_offset_public_key()
Expand Down Expand Up @@ -277,7 +277,7 @@ impl From<TransactionOutput> for proto::types::TransactionOutput {
features: Some(output.features.into()),
commitment: Some(output.commitment.into()),
range_proof: output.proof.to_vec(),
script: output.script.as_bytes(),
script: output.script.to_bytes(),
sender_offset_public_key: output.sender_offset_public_key.as_bytes().to_vec(),
metadata_signature: Some(output.metadata_signature.into()),
covenant: output.covenant.to_bytes(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ impl From<SingleRoundSenderData> for proto::SingleRoundSenderData {
metadata: Some(sender_data.metadata.into()),
message: sender_data.message,
features: Some(sender_data.features.into()),
script: sender_data.script.as_bytes(),
script: sender_data.script.to_bytes(),
sender_offset_public_key: sender_data.sender_offset_public_key.to_vec(),
public_commitment_nonce: sender_data.public_commitment_nonce.to_vec(),
covenant: sender_data.covenant.to_consensus_bytes(),
Expand Down
2 changes: 1 addition & 1 deletion base_layer/core/tests/chain_storage_tests/chain_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1852,7 +1852,7 @@ mod malleability {
fn script() {
check_output_malleability(|block: &mut Block| {
let output = &mut block.body.outputs_mut()[0];
let mut script_bytes = output.script.as_bytes();
let mut script_bytes = output.script.to_bytes();
Opcode::PushZero.to_bytes(&mut script_bytes);
let mod_script = TariScript::from_bytes(&script_bytes).unwrap();
output.script = mod_script;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1417,8 +1417,8 @@ impl From<KnownOneSidedPaymentScript> for KnownOneSidedPaymentScriptSql {
let script_lock_height = known_script.script_lock_height as i64;
let script_hash = known_script.script_hash;
let private_key = known_script.private_key.as_bytes().to_vec();
let script = known_script.script.as_bytes().to_vec();
let input = known_script.input.as_bytes().to_vec();
let script = known_script.script.to_bytes().to_vec();
let input = known_script.input.to_bytes().to_vec();
KnownOneSidedPaymentScriptSql {
script_hash,
private_key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ impl NewOutputSql {
status: status as i32,
received_in_tx_id: received_in_tx_id.map(|i| i.as_u64() as i64),
hash: Some(output.hash.to_vec()),
script: output.unblinded_output.script.as_bytes(),
input_data: output.unblinded_output.input_data.as_bytes(),
script: output.unblinded_output.script.to_bytes(),
input_data: output.unblinded_output.input_data.to_bytes(),
script_private_key: output.unblinded_output.script_private_key.to_vec(),
metadata: Some(output.unblinded_output.features.metadata.clone()),
sender_offset_public_key: output.unblinded_output.sender_offset_public_key.to_vec(),
Expand Down
10 changes: 5 additions & 5 deletions infrastructure/tari_script/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ impl TariScript {
}
}

pub fn as_bytes(&self) -> Vec<u8> {
pub fn to_bytes(&self) -> Vec<u8> {
self.script.iter().fold(Vec::new(), |mut bytes, op| {
op.to_bytes(&mut bytes);
bytes
Expand All @@ -137,7 +137,7 @@ impl TariScript {
if D::output_size() < 32 {
return Err(ScriptError::InvalidDigest);
}
let h = D::digest(&self.as_bytes());
let h = D::digest(&self.to_bytes());
Ok(slice_to_hash(&h.as_slice()[..32]))
}

Expand Down Expand Up @@ -178,7 +178,7 @@ impl TariScript {
pub fn script_message(&self, pub_key: &RistrettoPublicKey) -> Result<RistrettoSecretKey, ScriptError> {
let b = Blake256::new()
.chain(pub_key.as_bytes())
.chain(&self.as_bytes())
.chain(&self.to_bytes())
.finalize();
RistrettoSecretKey::from_bytes(b.as_slice()).map_err(|_| ScriptError::InvalidSignature)
}
Expand Down Expand Up @@ -562,7 +562,7 @@ impl Hex for TariScript {
}

fn to_hex(&self) -> String {
to_hex(&self.as_bytes())
to_hex(&self.to_bytes())
}
}

Expand Down Expand Up @@ -948,7 +948,7 @@ mod test {
#[test]
fn serialisation() {
let script = script!(Add Sub Add);
assert_eq!(&script.as_bytes(), &[0x93, 0x94, 0x93]);
assert_eq!(&script.to_bytes(), &[0x93, 0x94, 0x93]);
assert_eq!(TariScript::from_bytes(&[0x93, 0x94, 0x93]).unwrap(), script);
assert_eq!(script.to_hex(), "939493");
assert_eq!(TariScript::from_hex("939493").unwrap(), script);
Expand Down
107 changes: 81 additions & 26 deletions infrastructure/tari_script/src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ use serde::{
};
use tari_utilities::hex::{from_hex, Hex};

use crate::TariScript;
use crate::{ExecutionStack, TariScript};

impl Serialize for TariScript {
fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where S: Serializer {
let script_bin = self.as_bytes();
let script_bin = self.to_bytes();
if ser.is_human_readable() {
ser.serialize_str(&script_bin.to_hex())
} else {
Expand All @@ -40,44 +40,99 @@ impl Serialize for TariScript {
}
}

struct ScriptVisitor;
impl<'de> Deserialize<'de> for TariScript {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
struct ScriptVisitor;

impl<'de> Visitor<'de> for ScriptVisitor {
type Value = TariScript;
impl<'de> Visitor<'de> for ScriptVisitor {
type Value = TariScript;

fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("Expecting a binary array or hex string")
}
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("Expecting a binary array or hex string")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: Error {
let bytes = from_hex(v).map_err(|e| E::custom(e.to_string()))?;
self.visit_bytes(&bytes)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: Error {
let bytes = from_hex(v).map_err(|e| E::custom(e.to_string()))?;
self.visit_bytes(&bytes)
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: Error {
self.visit_str(&v)
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: Error {
self.visit_str(&v)
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: Error {
TariScript::from_bytes(v).map_err(|e| E::custom(e.to_string()))
}

fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
where E: Error {
self.visit_bytes(v)
}
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: Error {
TariScript::from_bytes(v).map_err(|e| E::custom(e.to_string()))
if de.is_human_readable() {
de.deserialize_string(ScriptVisitor)
} else {
de.deserialize_bytes(ScriptVisitor)
}
}
}

fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
where E: Error {
self.visit_bytes(v)
// -------------------------------- ExecutionStack -------------------------------- //
impl Serialize for ExecutionStack {
fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where S: Serializer {
let stack_bin = self.to_bytes();
if ser.is_human_readable() {
ser.serialize_str(&stack_bin.to_hex())
} else {
ser.serialize_bytes(&stack_bin)
}
}
}

impl<'de> Deserialize<'de> for TariScript {
impl<'de> Deserialize<'de> for ExecutionStack {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
struct ExecutionStackVisitor;

impl<'de> Visitor<'de> for ExecutionStackVisitor {
type Value = ExecutionStack;

fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("Expecting a binary array or hex string")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: Error {
let bytes = from_hex(v).map_err(|e| E::custom(e.to_string()))?;
self.visit_bytes(&bytes)
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: Error {
self.visit_str(&v)
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: Error {
ExecutionStack::from_bytes(v).map_err(|e| E::custom(e.to_string()))
}

fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
where E: Error {
self.visit_bytes(v)
}
}

if de.is_human_readable() {
de.deserialize_string(ScriptVisitor)
de.deserialize_string(ExecutionStackVisitor)
} else {
de.deserialize_bytes(ScriptVisitor)
de.deserialize_bytes(ExecutionStackVisitor)
}
}
}
11 changes: 5 additions & 6 deletions infrastructure/tari_script/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

use std::convert::TryFrom;

use serde::{Deserialize, Serialize};
use tari_crypto::ristretto::{pedersen::PedersenCommitment, RistrettoPublicKey, RistrettoSchnorr, RistrettoSecretKey};
use tari_utilities::{
hex::{from_hex, to_hex, Hex, HexError},
Expand Down Expand Up @@ -58,7 +57,7 @@ pub const TYPE_PUBKEY: u8 = 4;
pub const TYPE_SIG: u8 = 5;
pub const TYPE_SCALAR: u8 = 6;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StackItem {
Number(i64),
Hash(HashValue),
Expand Down Expand Up @@ -178,7 +177,7 @@ stack_item_from!(RistrettoPublicKey => PublicKey);
stack_item_from!(RistrettoSchnorr => Signature);
stack_item_from!(ScalarValue => Scalar);

#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ExecutionStack {
items: Vec<StackItem>,
}
Expand Down Expand Up @@ -262,7 +261,7 @@ impl ExecutionStack {
}

/// Return a binary array representation of the input stack
pub fn as_bytes(&self) -> Vec<u8> {
pub fn to_bytes(&self) -> Vec<u8> {
self.items.iter().fold(Vec::new(), |mut bytes, item| {
item.to_bytes(&mut bytes);
bytes
Expand Down Expand Up @@ -317,7 +316,7 @@ impl Hex for ExecutionStack {
}

fn to_hex(&self) -> String {
to_hex(&self.as_bytes())
to_hex(&self.to_bytes())
}
}

Expand Down Expand Up @@ -378,7 +377,7 @@ mod test {
} = utils::sign::<Blake256>(&k, b"hi").unwrap();
let items = vec![Number(5432), Number(21), Signature(s), PublicKey(p)];
let stack = ExecutionStack::new(items);
let bytes = stack.as_bytes();
let bytes = stack.to_bytes();
let stack2 = ExecutionStack::from_bytes(&bytes).unwrap();
assert_eq!(stack, stack2);
}
Expand Down

0 comments on commit b6feb5f

Please sign in to comment.