Skip to content

Commit

Permalink
feat(dan_layer)!: generate and add checkpoint signatures (#4261)
Browse files Browse the repository at this point in the history
Description
---
- feat(dan_layer): generate and add checkpoint signatures
- feat(explorer): update text explorer to include signatures
-  feat(base_layer/wallet): update wallet command file formats
-  feat(base_layer/core): wires up committee signatures to grpc with conversions
-  feat(base_layer/core): adds SignerSignature struct for CommitteeSignatures
-  feat(base_layer/wallet): include committee signatures for checkpoint GRPC requests

Motivation and Context
---
DAN committees need to collect signatures to include in checkpoints. This PR adds the initial implementation of that.
The signature challenge is: 

`e = H_1(signer_public_key || public_nonce || H_2(contract_id||commitment||merkle_root||checkpoint_number))`

Although constructing a challenge with actual data is a TODO as that involves a bit of a refactor.

This PR also adds the `SignerSignature` struct that includes the signing public key along with the Schnorr signature tuple `<R, s>`. This is so that we know which if the validators signed. There may be an aggregate signature scheme that allows this.

How Has This Been Tested?
---
Manually, initial checkpoint contains signature.
  • Loading branch information
sdbondi authored Jul 6, 2022
1 parent bcd14c7 commit 0f581ca
Show file tree
Hide file tree
Showing 47 changed files with 587 additions and 148 deletions.
7 changes: 6 additions & 1 deletion applications/tari_app_grpc/proto/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,12 @@ message ContractAmendment {
}

message CommitteeSignatures {
repeated Signature signatures = 1;
repeated SignerSignature signatures = 1;
}

message SignerSignature {
bytes signer = 1;
Signature signature = 2;
}

// TODO: DEPRECATED
Expand Down
3 changes: 2 additions & 1 deletion applications/tari_app_grpc/proto/wallet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ message RegisterAssetResponse {
message CreateInitialAssetCheckpointRequest {
bytes contract_id = 1;
bytes merkle_root = 2;
repeated bytes committee = 3;
CommitteeSignatures committee_signatures = 3;
}

message CreateInitialAssetCheckpointResponse {
Expand All @@ -282,6 +282,7 @@ message CreateFollowOnAssetCheckpointRequest {
uint64 checkpoint_number = 1;
bytes contract_id = 2;
bytes merkle_root = 3;
CommitteeSignatures committee_signatures = 4;
}

message CreateFollowOnAssetCheckpointResponse {
Expand Down
35 changes: 31 additions & 4 deletions applications/tari_app_grpc/src/conversions/sidechain_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
// 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, TryInto};
use std::{
borrow::Borrow,
convert::{TryFrom, TryInto},
};

use tari_common_types::types::{FixedHash, PublicKey, Signature};
use tari_common_types::types::{FixedHash, PublicKey};
use tari_core::transactions::transaction_components::{
vec_into_fixed_string,
CheckpointParameters,
Expand All @@ -44,6 +47,7 @@ use tari_core::transactions::transaction_components::{
RequirementsForConstitutionChange,
SideChainConsensus,
SideChainFeatures,
SignerSignature,
};
use tari_utilities::ByteArray;

Expand Down Expand Up @@ -489,7 +493,7 @@ impl TryFrom<grpc::CommitteeMembers> for CommitteeMembers {
impl From<CommitteeSignatures> for grpc::CommitteeSignatures {
fn from(value: CommitteeSignatures) -> Self {
Self {
signatures: value.signatures().into_iter().map(Into::into).collect(),
signatures: value.signatures().iter().map(Into::into).collect(),
}
}
}
Expand All @@ -511,7 +515,7 @@ impl TryFrom<grpc::CommitteeSignatures> for CommitteeSignatures {
.into_iter()
.enumerate()
.map(|(i, s)| {
Signature::try_from(s)
SignerSignature::try_from(s)
.map_err(|err| format!("committee signature #{} was not a valid signature: {}", i + 1, err))
})
.collect::<Result<Vec<_>, _>>()?;
Expand All @@ -521,6 +525,29 @@ impl TryFrom<grpc::CommitteeSignatures> for CommitteeSignatures {
}
}

//---------------------------------- SignerSignature --------------------------------------------//
impl<B: Borrow<SignerSignature>> From<B> for grpc::SignerSignature {
fn from(value: B) -> Self {
Self {
signer: value.borrow().signer.to_vec(),
signature: Some(grpc::Signature::from(&value.borrow().signature)),
}
}
}

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

fn try_from(value: grpc::SignerSignature) -> Result<Self, Self::Error> {
Ok(Self {
signer: PublicKey::from_bytes(&value.signer).map_err(|err| err.to_string())?,
signature: value
.signature
.map(TryInto::try_into)
.ok_or("signature not provided")??,
})
}
}
//---------------------------------- ContractAcceptance --------------------------------------------//

impl From<ContractAcceptance> for grpc::ContractAcceptance {
Expand Down
10 changes: 5 additions & 5 deletions applications/tari_app_grpc/src/conversions/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// 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 std::{borrow::Borrow, convert::TryFrom};

use tari_common_types::types::{PrivateKey, PublicKey, Signature};
use tari_utilities::ByteArray;
Expand All @@ -39,11 +39,11 @@ impl TryFrom<grpc::Signature> for Signature {
}
}

impl From<Signature> for grpc::Signature {
fn from(sig: Signature) -> Self {
impl<T: Borrow<Signature>> From<T> for grpc::Signature {
fn from(sig: T) -> Self {
Self {
public_nonce: sig.get_public_nonce().to_vec(),
signature: sig.get_signature().to_vec(),
public_nonce: sig.borrow().get_public_nonce().to_vec(),
signature: sig.borrow().get_signature().to_vec(),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,11 @@ impl WalletClient {
merkle_root: Vec<u8>,
) -> Result<grpc::CreateInitialAssetCheckpointResponse, CollectiblesError> {
let inner = self.get_inner_mut()?;
let committee = vec![];
let request = grpc::CreateInitialAssetCheckpointRequest {
// TODO: contract id
contract_id: Vec::from_hex(asset_public_key)?,
merkle_root,
committee,
committee_signatures: None,
};
let result = inner
.create_initial_asset_checkpoint(request)
Expand Down
18 changes: 16 additions & 2 deletions applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,8 +831,15 @@ impl wallet_server::Wallet for WalletGrpcServer {
.try_into()
.map_err(|_| Status::invalid_argument("Merkle root has an incorrect length"))?;

let committee_signatures = message
.committee_signatures
.map(TryInto::try_into)
.transpose()
.map_err(|_| Status::invalid_argument("Invalid committee signatures"))?
.unwrap_or_default();

let (tx_id, transaction) = asset_manager
.create_initial_asset_checkpoint(contract_id, merkle_root)
.create_initial_asset_checkpoint(contract_id, merkle_root, committee_signatures)
.await
.map_err(|e| Status::internal(e.to_string()))?;

Expand Down Expand Up @@ -865,8 +872,15 @@ impl wallet_server::Wallet for WalletGrpcServer {
.try_into()
.map_err(|_| Status::invalid_argument("Incorrect merkle root length"))?;

let committee_signatures = message
.committee_signatures
.map(TryInto::try_into)
.transpose()
.map_err(|_| Status::invalid_argument("Invalid committee signatures"))?
.unwrap_or_default();

let (tx_id, transaction) = asset_manager
.create_follow_on_asset_checkpoint(contract_id, checkpoint_number, merkle_root)
.create_follow_on_asset_checkpoint(contract_id, checkpoint_number, merkle_root, committee_signatures)
.await
.map_err(|e| Status::internal(e.to_string()))?;

Expand Down
6 changes: 4 additions & 2 deletions applications/tari_explorer/partials/CommitteeSignatures.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<dl>
<dt>Signatures</dt>
{{#if signatures}}
<dt>{{signatures.length}} signatures</dt>
{{#each signatures as |signature|}}
<dd>{{>Signature signature}}</dd>
<dd>{{>SignerSignature signature}}</dd>
{{/each}}
{{/if}}
</dl>
1 change: 1 addition & 0 deletions applications/tari_explorer/partials/ContractCheckpoint.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<dl>
<dt>Number</dt><dd>{{checkpoint_number}}</dd>
<dt>Merkle root</dt><dd>{{hex merkle_root}}</dd>
<dt>Signatures</dt><dd>{{>CommitteeSignatures signatures}}</dd>
</dl>
4 changes: 4 additions & 0 deletions applications/tari_explorer/partials/SignerSignature.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<dl>
<dt>Signer</dt><dd>{{hex signer}}</dd>
<dt>Signature</dt><dd>{{>Signature signature}}</dd>
</dl>
10 changes: 10 additions & 0 deletions applications/tari_validator_node/proto/dan/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,13 @@ message Instruction {
message InstructionSet{
repeated Instruction instructions = 1;
}

message SignerSignature {
bytes signer = 1;
Signature signature = 2;
}

message Signature {
bytes public_nonce = 1;
bytes signature = 2;
}
7 changes: 4 additions & 3 deletions applications/tari_validator_node/proto/dan/consensus.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@ message HotStuffMessage {
HotStuffMessageType message_type = 2;
QuorumCertificate justify = 3;
HotStuffTreeNode node= 4;
Signature partial_sig = 5;
ValidatorSignature partial_sig = 5;
bytes node_hash = 6;
bytes contract_id = 7;
tari.dan.common.SignerSignature checkpoint_signature = 8;
}

message QuorumCertificate {
HotStuffMessageType message_type = 1;
bytes node_hash = 2;
uint64 view_number = 3;
Signature signature = 4;
ValidatorSignature signature = 4;
}

message HotStuffTreeNode {
Expand All @@ -41,7 +42,7 @@ message HotStuffTreeNode {
bytes state_root =4;
}

message Signature{
message ValidatorSignature{

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,7 @@ impl ContractWorkerManager {
pub async fn start(mut self) -> Result<(), WorkerManagerError> {
self.load_initial_state()?;

if self.config.constitution_auto_accept {
info!("constitution_auto_accept is true");
}
info!("constitution_auto_accept is {}", self.config.constitution_auto_accept);

if !self.config.scan_for_assets {
info!(
Expand Down Expand Up @@ -180,7 +178,7 @@ impl ContractWorkerManager {
for contract in active_contracts {
let contract_id = FixedHash::try_from(contract.contract_id)?;

println!("Starting contract {}", contract_id.to_hex());
println!("Starting contract {}", contract_id);

let constitution = ContractConstitution::from_binary(&*contract.constitution).map_err(|error| {
WorkerManagerError::DataCorruption {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use std::net::SocketAddr;

use async_trait::async_trait;
use log::*;
use tari_app_grpc::{
tari_rpc as grpc,
tari_rpc::{
Expand All @@ -33,10 +34,13 @@ use tari_app_grpc::{
},
};
use tari_common_types::types::{FixedHash, PublicKey, Signature};
use tari_core::transactions::transaction_components::SignerSignature;
use tari_crypto::tari_utilities::ByteArray;
use tari_dan_core::{services::WalletClient, DigitalAssetError};
use tari_dan_engine::state::models::StateRoot;

const LOG_TARGET: &str = "tari::dan::wallet_grpc";

type Inner = grpc::wallet_client::WalletClient<tonic::transport::Channel>;

#[derive(Clone)]
Expand Down Expand Up @@ -69,14 +73,20 @@ impl WalletClient for GrpcWalletClient {
contract_id: &FixedHash,
state_root: &StateRoot,
checkpoint_number: u64,
checkpoint_signatures: Vec<SignerSignature>,
) -> Result<(), DigitalAssetError> {
let inner = self.connection().await?;
let committee_signatures = grpc::CommitteeSignatures {
signatures: checkpoint_signatures.into_iter().map(Into::into).collect(),
};

info!(target: LOG_TARGET, "✅ Creating checkpoint #{}", checkpoint_number);

if checkpoint_number == 0 {
let request = CreateInitialAssetCheckpointRequest {
contract_id: contract_id.to_vec(),
merkle_root: state_root.as_bytes().to_vec(),
committee: vec![],
committee_signatures: Some(committee_signatures),
};

let _res = inner
Expand All @@ -88,6 +98,7 @@ impl WalletClient for GrpcWalletClient {
checkpoint_number,
contract_id: contract_id.to_vec(),
merkle_root: state_root.as_bytes().to_vec(),
committee_signatures: Some(committee_signatures),
};

let _res = inner
Expand Down
Loading

0 comments on commit 0f581ca

Please sign in to comment.