Skip to content

Commit

Permalink
feat: Change script_signature type to ComSig (#3016)
Browse files Browse the repository at this point in the history
  • Loading branch information
stringhandler committed Jun 30, 2021
2 parents 04f826d + 57ce1ac commit adb4a64
Show file tree
Hide file tree
Showing 19 changed files with 216 additions and 4,337 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion applications/tari_app_grpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ edition = "2018"
tari_common_types = { version = "^0.8", path = "../../base_layer/common_types"}
tari_core = { path = "../../base_layer/core"}
tari_wallet = { path = "../../base_layer/wallet"}
tari_crypto = { git = "ssh://git@github.com/tari-project/tari-crypto.git", branch = "main" }
tari_crypto = { git = "ssh://git@github.com/tari-project/tari-crypto.git", branch = "main" } #switch back to official after merge
tari_comms = { path = "../../comms"}

chrono = "0.4.6"
Expand Down
16 changes: 12 additions & 4 deletions applications/tari_app_grpc/proto/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ message HistoricalBlock {
}


// The NewBlockHeaderTemplate is used for the construction of a new mineable block. It contains all the metadata for the block that the Base Node is able to complete on behalf of a Miner.
// The NewBlockHeaderTemplate is used for the construction of a new mine-able block. It contains all the metadata for the block that the Base Node is able to complete on behalf of a Miner.
message NewBlockHeaderTemplate {
// Version of the block
uint32 version = 1;
Expand Down Expand Up @@ -167,8 +167,8 @@ message TransactionInput {
// The block height that the UTXO was mined
uint64 height = 6;
// A signature with k_s, signing the script, input data, and mined height
Signature script_signature = 7;
// The offset pubkey, K_O
ComSignature script_signature = 7;
// The offset public key, K_O
bytes script_offset_public_key = 8;
}

Expand All @@ -186,7 +186,7 @@ message TransactionOutput {
bytes hash = 4;
// Tari script serialised script
bytes script = 5;
// Tari script offset pubkey, K_O
// Tari script offset public key, K_O
bytes script_offset_public_key = 6;
// UTXO signature with the script offset private key, k_O
Signature sender_metadata_signature = 7;
Expand Down Expand Up @@ -227,6 +227,14 @@ message Signature {
bytes signature = 2;
}

// Define the explicit ComSignature implementation for the Tari base layer. A different signature scheme can be
// employed by redefining this type.
message ComSignature {
bytes public_nonce_commitment = 1;
bytes signature_u = 2;
bytes signature_v = 3;
}

/// Consensus Constants response
message ConsensusConstants {
/// The min height maturity a coinbase utxo must have
Expand Down
42 changes: 42 additions & 0 deletions applications/tari_app_grpc/src/conversions/com_signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2020. 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.

use std::convert::TryFrom;
use tari_crypto::tari_utilities::ByteArray;

use crate::tari_rpc as grpc;
use tari_core::transactions::types::{ComSignature, Commitment, PrivateKey};

impl TryFrom<grpc::ComSignature> for ComSignature {
type Error = String;

fn try_from(sig: grpc::ComSignature) -> Result<Self, Self::Error> {
let public_nonce = Commitment::from_bytes(&sig.public_nonce_commitment)
.map_err(|_| "Could not get public nonce commitment".to_string())?;
let signature_u =
PrivateKey::from_bytes(&sig.signature_u).map_err(|_| "Could not get partial signature u".to_string())?;
let signature_v =
PrivateKey::from_bytes(&sig.signature_v).map_err(|_| "Could not get partial signature v".to_string())?;

Ok(Self::new(public_nonce, signature_u, signature_v))
}
}
2 changes: 2 additions & 0 deletions applications/tari_app_grpc/src/conversions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod aggregate_body;
mod block;
mod block_header;
mod chain_metadata;
mod com_signature;
mod consensus_constants;
mod historical_block;
mod new_block_template;
Expand All @@ -42,6 +43,7 @@ pub use self::{
block::*,
block_header::*,
chain_metadata::*,
com_signature::*,
consensus_constants::*,
historical_block::*,
new_block_template::*,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ impl From<TransactionInput> for grpc::TransactionInput {
script: input.script.as_bytes(),
input_data: input.input_data.as_bytes(),
height: input.height,
script_signature: Some(grpc::Signature {
public_nonce: Vec::from(input.script_signature.get_public_nonce().as_bytes()),
signature: Vec::from(input.script_signature.get_signature().as_bytes()),
script_signature: Some(grpc::ComSignature {
public_nonce_commitment: Vec::from(input.script_signature.public_nonce().as_bytes()),
signature_u: Vec::from(input.script_signature.u().as_bytes()),
signature_v: Vec::from(input.script_signature.v().as_bytes()),
}),
script_offset_public_key: input.script_offset_public_key.as_bytes().to_vec(),
}
Expand Down
1 change: 0 additions & 1 deletion applications/tari_console_wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,3 @@ features = ["transactions", "mempool_proto", "base_node_proto"]
version = "^0.12"
default-features = false
features = ["crossterm"]

4 changes: 2 additions & 2 deletions base_layer/core/src/blocks/genesis_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub fn get_mainnet_genesis_block() -> ChainBlock {
pub fn get_stibbons_genesis_block() -> ChainBlock {
// lets get the block
let mut block = get_stibbons_genesis_block_raw();
// Lets load in the stibbons faucet tx's
// Lets load in the stibbons faucet transactions
let mut utxos = Vec::new();
let file = include_str!("faucets/stibbons_faucet.json");
// last 2 lines are used for the kernel creation
Expand Down Expand Up @@ -88,7 +88,7 @@ pub fn get_stibbons_genesis_block() -> ChainBlock {
pub fn get_weatherwax_genesis_block() -> ChainBlock {
// lets get the block
let mut block = get_weatherwax_genesis_block_raw();
// Lets load in the weatherwax faucet tx's
// Lets load in the weatherwax faucet transactions
let mut utxos = Vec::new();
let file = include_str!("faucets/weatherwax_faucet.json");
// last 2 lines are used for the kernel creation
Expand Down
2 changes: 1 addition & 1 deletion base_layer/core/src/proto/transaction.proto
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ message TransactionInput {
// The block height that the UTXO was mined
uint64 height = 5;
// A signature with k_s, signing the script, input data, and mined height
Signature script_signature = 6;
ComSignature script_signature = 6;
// The offset pubkey, K_O
bytes script_offset_public_key = 7;
}
Expand Down
8 changes: 8 additions & 0 deletions base_layer/core/src/proto/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ message Signature {
bytes signature = 2;
}

// Define the explicit ComSignature implementation for the Tari base layer. A different signature scheme can be
// employed by redefining this type.
message ComSignature {
bytes public_nonce_commitment = 1;
bytes signature_u = 2;
bytes signature_v = 3;
}

// BlindingFactor wrapper
message BlindingFactor {
bytes data = 1;
Expand Down
34 changes: 33 additions & 1 deletion base_layer/core/src/proto/types_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use super::types as proto;
use crate::transactions::types::{BlindingFactor, Commitment, HashOutput, PrivateKey, PublicKey, Signature};
use crate::transactions::types::{
BlindingFactor,
ComSignature,
Commitment,
HashOutput,
PrivateKey,
PublicKey,
Signature,
};
use std::convert::TryFrom;
use tari_crypto::tari_utilities::{ByteArray, ByteArrayError};

Expand Down Expand Up @@ -65,6 +73,30 @@ impl From<Signature> for proto::Signature {
}
}

//---------------------------------- ComSignature --------------------------------------------//

impl TryFrom<proto::ComSignature> for ComSignature {
type Error = ByteArrayError;

fn try_from(sig: proto::ComSignature) -> Result<Self, Self::Error> {
let public_nonce = Commitment::from_bytes(&sig.public_nonce_commitment)?;
let signature_u = PrivateKey::from_bytes(&sig.signature_u)?;
let signature_v = PrivateKey::from_bytes(&sig.signature_v)?;

Ok(Self::new(public_nonce, signature_u, signature_v))
}
}

impl From<ComSignature> for proto::ComSignature {
fn from(sig: ComSignature) -> Self {
Self {
public_nonce_commitment: sig.public_nonce().to_vec(),
signature_u: sig.u().to_vec(),
signature_v: sig.v().to_vec(),
}
}
}

//---------------------------------- HashOutput --------------------------------------------//

impl From<proto::HashOutput> for HashOutput {
Expand Down
10 changes: 7 additions & 3 deletions base_layer/core/src/transactions/aggregated_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl AggregateBody {

self.validate_range_proofs(&factories.range_proof)?;
self.validate_sender_signatures()?;
self.validate_script_offset(script_offset_g)
self.validate_script_offset(script_offset_g, &factories.commitment)
}

pub fn dissolve(self) -> (Vec<TransactionInput>, Vec<TransactionOutput>, Vec<TransactionKernel>) {
Expand Down Expand Up @@ -378,12 +378,16 @@ impl AggregateBody {
}

/// this will validate the script offset of the aggregate body.
fn validate_script_offset(&self, script_offset: PublicKey) -> Result<(), TransactionError> {
fn validate_script_offset(
&self,
script_offset: PublicKey,
factory: &CommitmentFactory,
) -> Result<(), TransactionError> {
trace!(target: LOG_TARGET, "Checking script offset");
// lets count up the input script public keys
let mut input_keys = PublicKey::default();
for input in &self.inputs {
input_keys = input_keys + input.run_and_verify_script()?;
input_keys = input_keys + input.run_and_verify_script(factory)?;
}

// Now lets gather the output public keys and hashes.
Expand Down
58 changes: 38 additions & 20 deletions base_layer/core/src/transactions/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::transactions::{
types::{
BlindingFactor,
Challenge,
ComSignature,
Commitment,
CommitmentFactory,
CryptoFactories,
Expand Down Expand Up @@ -244,18 +245,27 @@ impl UnblindedOutput {
/// Commits an UnblindedOutput into a Transaction input
pub fn as_transaction_input(&self, factory: &CommitmentFactory) -> Result<TransactionInput, TransactionError> {
let commitment = factory.commit(&self.spending_key, &self.value.into());
let script_nonce = PrivateKey::random(&mut OsRng);
let public_script_nonce = PublicKey::from_secret_key(&script_nonce);
let script_nonce_a = PrivateKey::random(&mut OsRng);
let script_nonce_b = PrivateKey::random(&mut OsRng);
let nonce_commitment = factory.commit(&script_nonce_b, &script_nonce_a);

let e = Challenge::new()
.chain(public_script_nonce.as_bytes())
.chain(nonce_commitment.as_bytes())
.chain(self.script.as_bytes().as_slice())
.chain(self.input_data.as_bytes().as_slice())
//.chain(&self.height.to_le_bytes()) //TODO decide if the height should remain in this signature
.chain(PublicKey::from_secret_key(&self.script_private_key).as_bytes())
.chain(commitment.as_bytes())
.result()
.to_vec();

let script_signature = Signature::sign(self.script_private_key.clone(), script_nonce, &e)
.map_err(|_| TransactionError::InvalidSignatureError("Generating script signature".to_string()))?;
let script_signature = ComSignature::sign(
self.value.into(),
self.script_private_key.clone() + self.spending_key.clone(),
script_nonce_a,
script_nonce_b,
&e,
factory,
)
.map_err(|_| TransactionError::InvalidSignatureError("Generating script signature".to_string()))?;

Ok(TransactionInput {
features: self.features.clone(),
Expand Down Expand Up @@ -373,7 +383,7 @@ pub struct TransactionInput {
/// The block height that the UTXO was mined
pub height: u64,
/// A signature with k_s, signing the script, input data, and mined height
pub script_signature: Signature,
pub script_signature: ComSignature,
/// The offset pubkey, K_O
pub script_offset_public_key: PublicKey,
}
Expand All @@ -387,7 +397,7 @@ impl TransactionInput {
script: TariScript,
input_data: ExecutionStack,
height: u64,
script_signature: Signature,
script_signature: ComSignature,
script_offset_public_key: PublicKey,
) -> TransactionInput {
TransactionInput {
Expand Down Expand Up @@ -428,16 +438,24 @@ impl TransactionInput {
}
}

pub fn validate_script_signature(&self, key: &PublicKey) -> Result<(), TransactionError> {
let r = self.script_signature.get_public_nonce();
let m = HashDigest::new()
.chain(r.as_bytes())
.chain(self.script.as_bytes())
.chain(self.input_data.as_bytes())
//.chain(self.height.to_le_bytes()) //TODO decide if the height should remain in the script signature
pub fn validate_script_signature(
&self,
public_script_key: &PublicKey,
factory: &CommitmentFactory,
) -> Result<(), TransactionError> {
let nonce_commitment = self.script_signature.public_nonce();
let m = Challenge::new()
.chain(nonce_commitment.as_bytes())
.chain(self.script.as_bytes().as_slice())
.chain(self.input_data.as_bytes().as_slice())
.chain(public_script_key.as_bytes())
.chain(self.commitment.as_bytes())
.result()
.to_vec();
if self.script_signature.verify_challenge(key, &m) {
if self
.script_signature
.verify_challenge(&(&self.commitment + public_script_key), &m, factory)
{
Ok(())
} else {
Err(TransactionError::InvalidSignatureError(
Expand All @@ -448,9 +466,9 @@ impl TransactionInput {

/// This will run the script and verify the script signature. If its valid, it will return the resulting public key
/// from the script.
pub fn run_and_verify_script(&self) -> Result<PublicKey, TransactionError> {
pub fn run_and_verify_script(&self, factory: &CommitmentFactory) -> Result<PublicKey, TransactionError> {
let key = self.run_script()?;
self.validate_script_signature(&key)?;
self.validate_script_signature(&key, factory)?;
Ok(key)
}
}
Expand Down Expand Up @@ -1316,7 +1334,7 @@ mod test {
let script = TariScript::default();
let input_data = ExecutionStack::default();
let height = 0;
let script_signature = Signature::default();
let script_signature = ComSignature::default();
let offset_pub_key = PublicKey::default();
let mut input = TransactionInput::new(
OutputFeatures::default(),
Expand Down
3 changes: 3 additions & 0 deletions base_layer/core/src/transactions/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use tari_crypto::{
ristretto::{
dalek_range_proof::DalekRangeProofService,
pedersen::{PedersenCommitment, PedersenCommitmentFactory},
RistrettoComSig,
RistrettoPublicKey,
RistrettoSchnorr,
RistrettoSecretKey,
Expand All @@ -36,6 +37,8 @@ use tari_crypto::{
/// Define the explicit Signature implementation for the Tari base layer. A different signature scheme can be
/// employed by redefining this type.
pub type Signature = RistrettoSchnorr;
/// Define the explicit Commitment Signature implementation for the Tari base layer.
pub type ComSignature = RistrettoComSig;

/// Define the explicit Commitment implementation for the Tari base layer.
pub type Commitment = PedersenCommitment;
Expand Down
Loading

0 comments on commit adb4a64

Please sign in to comment.