Skip to content

Commit

Permalink
feat: add encrypted_value to the UnblindedOutput (#4142)
Browse files Browse the repository at this point in the history
Description
---
The PR adds extra encrypted field to `UnblindedOutput` structs.

What was done:
- Added `EncryptedValue` struct
- Implemented `ConsensusEncode`, `ConsensusDecode` and `ByteArray` for it
- Added the `encrypted_value` field of that type to the `UnblindedOutput` struct
- Added an extra parameter to metadata signature calculation methods
- Added an extra field to the `GRPC` protocol (`UnblindedOutput` type)
- Added an extra column and migrations for the `outputs` table
- The types `OutputSql` and `NewOutputSql` updated to store and restore the `EncryptedValue`

Important notes:
1. The value of `encrypted_value` passed as a parameter to the metadata signature evaluation but has not taken into account yet, because it will break the verification process of the `TransactionOutput` and we can complete that when the same `encrypted_value` field will be added to the `TransactionOutput` struct in the further PRs.
2. Real encryption process is not implemented yet. Instead of that I've added the method `todo_encrypt_from` that I used to mark the places where we have to put an encryption service and call it.

Motivation and Context
---
Add an encrypted amount to the `TransactionOutput`.

How Has This Been Tested?
---
CI
  • Loading branch information
therustmonk authored May 30, 2022
1 parent 5cc9a40 commit f79d383
Show file tree
Hide file tree
Showing 26 changed files with 269 additions and 33 deletions.
2 changes: 2 additions & 0 deletions applications/tari_app_grpc/proto/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ message UnblindedOutput {
uint64 script_lock_height = 10;
// Covenant
bytes covenant = 11;
// Encrypted Value
bytes encrypted_value = 12;
}

// ----------------------------- Network Types ----------------------------- //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use tari_core::{
covenants::Covenant,
transactions::{
tari_amount::MicroTari,
transaction_components::{TransactionOutputVersion, UnblindedOutput},
transaction_components::{EncryptedValue, TransactionOutputVersion, UnblindedOutput},
},
};
use tari_script::{ExecutionStack, TariScript};
Expand All @@ -52,6 +52,7 @@ impl From<UnblindedOutput> for grpc::UnblindedOutput {
}),
script_lock_height: output.script_lock_height,
covenant: output.covenant.to_bytes(),
encrypted_value: output.encrypted_value.to_vec(),
}
}
}
Expand Down Expand Up @@ -87,6 +88,8 @@ impl TryFrom<grpc::UnblindedOutput> for UnblindedOutput {

let covenant = Covenant::from_bytes(&output.covenant).map_err(|err| err.to_string())?;

let encrypted_value = EncryptedValue::from_bytes(&output.encrypted_value).map_err(|err| err.to_string())?;

Ok(Self::new(
TransactionOutputVersion::try_from(0u8)?,
MicroTari::from(output.value),
Expand All @@ -99,6 +102,7 @@ impl TryFrom<grpc::UnblindedOutput> for UnblindedOutput {
metadata_signature,
output.script_lock_height,
covenant,
encrypted_value,
))
}
}
3 changes: 3 additions & 0 deletions applications/test_faucet/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use tari_core::{
test_helpers,
test_helpers::generate_keys,
transaction_components::{
EncryptedValue,
KernelFeatures,
OutputFeatures,
TransactionKernel,
Expand Down Expand Up @@ -160,6 +161,7 @@ fn create_utxo(
let offset_keys = generate_keys();
let commitment = factories.commitment.commit_value(&keys.k, value.into());
let proof = factories.range_proof.construct_proof(&keys.k, value.into()).unwrap();
let encrypted_value = EncryptedValue::todo_encrypt_from(value);
let metadata_sig = TransactionOutput::create_final_metadata_signature(
TransactionOutputVersion::get_current_version(),
value,
Expand All @@ -168,6 +170,7 @@ fn create_utxo(
&features,
&offset_keys.k,
&covenant,
&encrypted_value,
)
.unwrap();

Expand Down
4 changes: 4 additions & 0 deletions base_layer/core/src/transactions/coinbase_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use crate::{
crypto_factories::CryptoFactories,
tari_amount::{uT, MicroTari},
transaction_components::{
EncryptedValue,
KernelBuilder,
KernelFeatures,
OutputFeatures,
Expand Down Expand Up @@ -205,6 +206,7 @@ impl CoinbaseBuilder {
let sender_offset_public_key = PublicKey::from_secret_key(&sender_offset_private_key);
let covenant = self.covenant;

let encrypted_value = EncryptedValue::todo_encrypt_from(total_reward);
let metadata_sig = TransactionOutput::create_final_metadata_signature(
TransactionOutputVersion::get_current_version(),
total_reward,
Expand All @@ -213,6 +215,7 @@ impl CoinbaseBuilder {
&output_features,
&sender_offset_private_key,
&covenant,
&encrypted_value,
)
.map_err(|e| CoinbaseBuildError::BuildError(e.to_string()))?;

Expand All @@ -227,6 +230,7 @@ impl CoinbaseBuilder {
metadata_sig,
0,
covenant,
encrypted_value,
);
let output = if let Some(rewind_data) = self.rewind_data.as_ref() {
unblinded_output
Expand Down
16 changes: 15 additions & 1 deletion base_layer/core/src/transactions/test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use tari_crypto::{
};
use tari_script::{inputs, script, ExecutionStack, TariScript};

use super::transaction_components::{TransactionInputVersion, TransactionOutputVersion};
use super::transaction_components::{EncryptedValue, TransactionInputVersion, TransactionOutputVersion};
use crate::{
consensus::{ConsensusEncodingSized, ConsensusManager},
covenants::Covenant,
Expand Down Expand Up @@ -178,6 +178,7 @@ impl TestParams {
let updated_features =
OutputFeatures::features_with_updated_recovery_byte(&commitment, rewind_data, &params.features);

let encrypted_value = EncryptedValue::todo_encrypt_from(params.value);
let metadata_signature = TransactionOutput::create_final_metadata_signature(
TransactionOutputVersion::get_current_version(),
params.value,
Expand All @@ -186,6 +187,7 @@ impl TestParams {
&updated_features,
&self.sender_offset_private_key,
&params.covenant,
&encrypted_value,
)
.unwrap();

Expand All @@ -205,6 +207,7 @@ impl TestParams {
metadata_signature,
0,
params.covenant,
encrypted_value,
)
}

Expand All @@ -221,6 +224,7 @@ impl TestParams {
&updated_features,
&self.sender_offset_private_key,
&uo.covenant,
&uo.encrypted_value,
)
.unwrap();

Expand All @@ -235,6 +239,7 @@ impl TestParams {
metadata_signature,
uo.script_lock_height,
uo.covenant,
uo.encrypted_value,
)
}

Expand Down Expand Up @@ -685,6 +690,7 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto
let commitment = factories
.commitment
.commit_value(&utxo.spending_key, utxo.value.as_u64());
let encrypted_value = EncryptedValue::todo_encrypt_from(utxo.value.as_u64());
let recovery_byte = OutputFeatures::create_unique_recovery_byte(&commitment, None);
utxo.features.set_recovery_byte(recovery_byte);
utxo.metadata_signature = TransactionOutput::create_final_metadata_signature(
Expand All @@ -695,6 +701,7 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto
&utxo.features,
&test_params.sender_offset_private_key,
&utxo.covenant,
&encrypted_value,
)
.unwrap();
utxo.sender_offset_public_key = test_params.sender_offset_public_key;
Expand All @@ -719,6 +726,9 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto
recovery_byte,
..Default::default()
};

// TODO: Get it using `something.encrypt_value(change)`
let encrypted_value = EncryptedValue::todo_encrypt_from(change);
let change_metadata_sig = TransactionOutput::create_final_metadata_signature(
output_version,
change,
Expand All @@ -727,6 +737,7 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto
&change_features,
&test_params_change_and_txn.sender_offset_private_key,
&covenant,
&encrypted_value,
)
.unwrap();

Expand All @@ -743,6 +754,7 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto
change_metadata_sig,
0,
covenant,
encrypted_value,
);
outputs.push(change_output);
(stx_protocol, outputs)
Expand Down Expand Up @@ -775,6 +787,7 @@ pub fn create_utxo(

let updated_features = OutputFeatures::features_with_updated_recovery_byte(&commitment, None, features);

let encrypted_value = EncryptedValue::todo_encrypt_from(value);
let metadata_sig = TransactionOutput::create_final_metadata_signature(
TransactionOutputVersion::get_current_version(),
value,
Expand All @@ -783,6 +796,7 @@ pub fn create_utxo(
&updated_features,
&offset_keys.k,
covenant,
&encrypted_value,
)
.unwrap();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2022 The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
//
// Portions of this file were originally copyrighted (c) 2018 The Grin Developers, issued under the Apache License,
// Version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0.

use std::io::{self, Read, Write};

use serde::{Deserialize, Serialize};
use tari_utilities::{ByteArray, ByteArrayError};

use crate::consensus::{ConsensusDecoding, ConsensusEncoding};

const SIZE: usize = 24;

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EncryptedValue {
/// value: u64 + tag: [u8; 16]
pub data: [u8; SIZE],
}

impl Default for EncryptedValue {
fn default() -> Self {
Self { data: [0; SIZE] }
}
}

impl ByteArray for EncryptedValue {
fn from_bytes(bytes: &[u8]) -> Result<Self, ByteArrayError> {
if bytes.len() == SIZE {
let mut this = Self::default();
this.data.copy_from_slice(bytes);
Ok(this)
} else {
Err(ByteArrayError::IncorrectLength)
}
}

fn as_bytes(&self) -> &[u8] {
&self.data
}
}

impl EncryptedValue {
/// TODO: Replace this method with a real call of encryption service
/// that will produce an encrypted value from the given `amount`.
pub fn todo_encrypt_from(amount: impl Into<u64>) -> Self {
let mut data: [u8; SIZE] = [0; SIZE];
let value = amount.into().to_le_bytes();
data[0..8].copy_from_slice(&value);
Self { data }
}
}

impl ConsensusEncoding for EncryptedValue {
fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
self.data.consensus_encode(writer)?;
Ok(())
}
}

impl ConsensusDecoding for EncryptedValue {
fn consensus_decode<R: Read>(reader: &mut R) -> Result<Self, io::Error> {
let data = <[u8; 24]>::consensus_decode(reader)?;
Ok(Self { data })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

pub use asset_output_features::AssetOutputFeatures;
pub use committee_definition_features::CommitteeDefinitionFeatures;
pub use encrypted_value::EncryptedValue;
pub use error::TransactionError;
pub use full_rewind_result::FullRewindResult;
pub use kernel_builder::KernelBuilder;
Expand Down Expand Up @@ -53,6 +54,7 @@ pub use unblinded_output_builder::UnblindedOutputBuilder;

mod asset_output_features;
mod committee_definition_features;
mod encrypted_value;
mod error;
mod full_rewind_result;
mod kernel_builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use crate::{
tari_amount::{uT, MicroTari, T},
test_helpers,
test_helpers::{create_sender_transaction_protocol_with, create_unblinded_txos, TestParams, UtxoTestParams},
transaction_components::OutputFeatures,
transaction_components::{EncryptedValue, OutputFeatures},
transaction_protocol::TransactionProtocolError,
CryptoFactories,
},
Expand Down Expand Up @@ -148,6 +148,7 @@ fn range_proof_verification() {
.construct_proof(&test_params_2.spend_key, 2u64.pow(32) + 1)
.unwrap();

let encrypted_value = EncryptedValue::todo_encrypt_from(value);
let tx_output3 = TransactionOutput::new_current_version(
output_features.clone(),
c,
Expand All @@ -162,6 +163,7 @@ fn range_proof_verification() {
&output_features,
&test_params_2.sender_offset_private_key,
&Covenant::default(),
&encrypted_value,
)
.unwrap(),
Covenant::default(),
Expand Down
Loading

0 comments on commit f79d383

Please sign in to comment.