Skip to content

Commit

Permalink
feat(core): add validator registration sidechain feature (#4690)
Browse files Browse the repository at this point in the history
Description
---
- add validator registration sidechain feature
- add basic VN signature
- add output feature for VN reg
- allow vn reg output feature in igor

Motivation and Context
---
DAN vn reg

How Has This Been Tested?
---
Existing tests
  • Loading branch information
sdbondi authored Sep 16, 2022
1 parent d9a0d79 commit 0fef174
Show file tree
Hide file tree
Showing 29 changed files with 439 additions and 240 deletions.
12 changes: 9 additions & 3 deletions applications/tari_app_grpc/proto/sidechain_types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ package tari.rpc;

import "types.proto";

message SideChainFeatures {
oneof side_chain_features {
TemplateRegistration template_registration = 1;
message SideChainFeature {
oneof side_chain_feature {
ValidatorNodeRegistration validator_node_registration = 1;
TemplateRegistration template_registration = 2;
}
}

message ValidatorNodeRegistration {
bytes public_key = 1;
Signature signature = 2;
}

message TemplateRegistration {
bytes author_public_key = 1;
Signature author_signature = 2;
Expand Down
4 changes: 1 addition & 3 deletions applications/tari_app_grpc/proto/transaction.proto
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,7 @@ message OutputFeatures {
// require a min maturity of the Coinbase_lock_height, this should be checked on receiving new blocks.
uint64 maturity = 3;
bytes metadata = 4;
SideChainFeatures sidechain_features = 5;
bytes validator_node_public_key = 6;
Signature validator_node_signature = 7;
SideChainFeature sidechain_feature = 5;
}


Expand Down
2 changes: 1 addition & 1 deletion applications/tari_app_grpc/src/conversions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ mod new_block_template;
mod output_features;
mod peer;
mod proof_of_work;
mod sidechain_features;
mod sidechain_feature;
mod signature;
mod transaction;
mod transaction_input;
Expand Down
29 changes: 7 additions & 22 deletions applications/tari_app_grpc/src/conversions/output_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,45 +22,38 @@

use std::convert::{TryFrom, TryInto};

use tari_common_types::types::PublicKey;
use tari_core::transactions::transaction_components::{
OutputFeatures,
OutputFeaturesVersion,
OutputType,
SideChainFeatures,
SideChainFeature,
};
use tari_utilities::ByteArray;

use crate::tari_rpc as grpc;

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

fn try_from(features: grpc::OutputFeatures) -> Result<Self, Self::Error> {
let sidechain_features = features
.sidechain_features
.and_then(|f| f.side_chain_features)
.map(SideChainFeatures::try_from)
let sidechain_feature = features
.sidechain_feature
.and_then(|f| f.side_chain_feature)
.map(SideChainFeature::try_from)
.transpose()?;

let output_type = features
.output_type
.try_into()
.map_err(|_| "Invalid output type: overflow")?;

let validator_node_public_key = PublicKey::from_vec(&features.validator_node_public_key).ok();
let validator_node_signature = features.validator_node_signature.map(|s| s.try_into()).transpose()?;

Ok(OutputFeatures::new(
OutputFeaturesVersion::try_from(
u8::try_from(features.version).map_err(|_| "Invalid version: overflowed u8")?,
)?,
OutputType::from_byte(output_type).ok_or_else(|| "Invalid or unrecognised output type".to_string())?,
features.maturity,
features.metadata,
sidechain_features,
validator_node_public_key,
validator_node_signature,
sidechain_feature,
))
}
}
Expand All @@ -72,15 +65,7 @@ impl From<OutputFeatures> for grpc::OutputFeatures {
output_type: u32::from(features.output_type.as_byte()),
maturity: features.maturity,
metadata: features.metadata,
sidechain_features: features.sidechain_features.map(Into::into),
validator_node_public_key: features
.validator_node_public_key
.map(|pk| pk.as_bytes().to_vec())
.unwrap_or_default(),
validator_node_signature: features.validator_node_signature.map(|s| grpc::Signature {
public_nonce: Vec::from(s.get_public_nonce().as_bytes()),
signature: Vec::from(s.get_signature().as_bytes()),
}),
sidechain_feature: features.sidechain_feature.map(Into::into),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,41 +25,77 @@ use std::convert::{TryFrom, TryInto};
use tari_common_types::types::{PublicKey, Signature};
use tari_core::{
consensus::MaxSizeString,
transactions::transaction_components::{BuildInfo, CodeTemplateRegistration, SideChainFeatures, TemplateType},
transactions::transaction_components::{
BuildInfo,
CodeTemplateRegistration,
SideChainFeature,
TemplateType,
ValidatorNodeRegistration,
},
};
use tari_utilities::ByteArray;

use crate::tari_rpc as grpc;

//---------------------------------- SideChainFeatures --------------------------------------------//
impl From<SideChainFeatures> for grpc::SideChainFeatures {
fn from(value: SideChainFeatures) -> Self {
//---------------------------------- SideChainFeature --------------------------------------------//
impl From<SideChainFeature> for grpc::SideChainFeature {
fn from(value: SideChainFeature) -> Self {
value.into()
}
}

impl From<SideChainFeatures> for grpc::side_chain_features::SideChainFeatures {
fn from(value: SideChainFeatures) -> Self {
impl From<SideChainFeature> for grpc::side_chain_feature::SideChainFeature {
fn from(value: SideChainFeature) -> Self {
match value {
SideChainFeatures::TemplateRegistration(template_reg) => {
grpc::side_chain_features::SideChainFeatures::TemplateRegistration(template_reg.into())
SideChainFeature::ValidatorNodeRegistration(template_reg) => {
grpc::side_chain_feature::SideChainFeature::ValidatorNodeRegistration(template_reg.into())
},
SideChainFeature::TemplateRegistration(template_reg) => {
grpc::side_chain_feature::SideChainFeature::TemplateRegistration(template_reg.into())
},
}
}
}

impl TryFrom<grpc::side_chain_features::SideChainFeatures> for SideChainFeatures {
impl TryFrom<grpc::side_chain_feature::SideChainFeature> for SideChainFeature {
type Error = String;

fn try_from(features: grpc::side_chain_features::SideChainFeatures) -> Result<Self, Self::Error> {
fn try_from(features: grpc::side_chain_feature::SideChainFeature) -> Result<Self, Self::Error> {
match features {
grpc::side_chain_features::SideChainFeatures::TemplateRegistration(template_reg) => {
Ok(SideChainFeatures::TemplateRegistration(template_reg.try_into()?))
grpc::side_chain_feature::SideChainFeature::ValidatorNodeRegistration(vn_reg) => {
Ok(SideChainFeature::ValidatorNodeRegistration(vn_reg.try_into()?))
},
grpc::side_chain_feature::SideChainFeature::TemplateRegistration(template_reg) => {
Ok(SideChainFeature::TemplateRegistration(template_reg.try_into()?))
},
}
}
}

// -------------------------------- ValidatorNodeRegistration -------------------------------- //
impl TryFrom<grpc::ValidatorNodeRegistration> for ValidatorNodeRegistration {
type Error = String;

fn try_from(value: grpc::ValidatorNodeRegistration) -> Result<Self, Self::Error> {
Ok(Self {
public_key: PublicKey::from_bytes(&value.public_key).map_err(|e| e.to_string())?,
signature: value
.signature
.map(Signature::try_from)
.ok_or("signature not provided")??,
})
}
}

impl From<ValidatorNodeRegistration> for grpc::ValidatorNodeRegistration {
fn from(value: ValidatorNodeRegistration) -> Self {
Self {
public_key: value.public_key.to_vec(),
signature: Some(value.signature.into()),
}
}
}

// -------------------------------- TemplateRegistration -------------------------------- //
impl TryFrom<grpc::TemplateRegistration> for CodeTemplateRegistration {
type Error = String;
Expand Down
10 changes: 2 additions & 8 deletions applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,7 @@ use tari_common_types::{
use tari_comms::{multiaddr::Multiaddr, types::CommsPublicKey, CommsNode};
use tari_core::transactions::{
tari_amount::{MicroTari, T},
transaction_components::{
CodeTemplateRegistration,
OutputFeatures,
OutputType,
SideChainFeatures,
UnblindedOutput,
},
transaction_components::{CodeTemplateRegistration, OutputFeatures, OutputType, SideChainFeature, UnblindedOutput},
};
use tari_utilities::{hex::Hex, ByteArray};
use tari_wallet::{
Expand Down Expand Up @@ -912,7 +906,7 @@ impl wallet_server::Wallet for WalletGrpcServer {
let output = output_manager
.create_output_with_features(1 * T, OutputFeatures {
output_type: OutputType::CodeTemplateRegistration,
sidechain_features: Some(SideChainFeatures::TemplateRegistration(template_registration)),
sidechain_feature: Some(SideChainFeature::TemplateRegistration(template_registration)),
..Default::default()
})
.await
Expand Down
11 changes: 1 addition & 10 deletions base_layer/core/src/blocks/genesis_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ use crate::{
EncryptedValue,
KernelFeatures,
OutputFeatures,
OutputFeaturesVersion,
OutputType,
TransactionKernel,
TransactionKernelVersion,
Expand Down Expand Up @@ -278,15 +277,7 @@ fn get_esmeralda_genesis_block_raw() -> Block {
);
let coinbase = TransactionOutput::new(
TransactionOutputVersion::get_current_version(),
OutputFeatures {
version: OutputFeaturesVersion::get_current_version(),
output_type: OutputType::Coinbase,
maturity: 6,
metadata: Vec::new(),
sidechain_features: None,
validator_node_public_key: None,
validator_node_signature: None,
},
OutputFeatures::create_coinbase(6),
Commitment::from_hex("46eec110cf173557e149d453734f6707fea9ed27c9a0dd0276bb43eb1f6e3322").unwrap(),
BulletRangeProof::from_hex("01b05c72ea976764b8f9a56bb302990829dacae5f9b2d26e028e97c66a7ac3a14c7809ea5da55fb1e88a16195619d67381f28181b1ad7e0c9661c726e1c56ad7770eb75e314b51a89d716a2dd7737b26a40d8e956911ff45d4c47a1164edae5505aaca58ec6f95762daaa02545dc2ce502e9892d98422849352b6dbcc3322b6b1adae4d33461dd8b5b75b4a9bf52b3e3b00ef7579b16e59f17f43c45ea5e82db063c23ce2d214f93a211cd8f7a3cb220071c68ba3a348b082c3eebb8b6d6339d18decd0372b82e762a9f16e5e7ed23b21c1025ba093b676c55cfa603d888bcc315bc95e8e4bebad9ec51124aab0fe4a8abfc9053db1fb1560c5214b9485826e0127448a2aa84c25f17c5833b15bf434903db7a676bfb11ace2ece255b018428457122da112d481c8a742f916cca069b874e6762248fbb00fa6895f7d4b8a9a8829164baf6ad1d3ad5775c679766ead9da782977fdeb5af7e4b2eb6828e87551179f888ed1c598dd1b81c46b335fb4a827fadf7669e007ff4ed6f260d0bde3eb42282983f58bb0f11a44e064a80503154f4cdb76537192411b2755c2b453b90b3754e9253e64837f15c933b7a479fbb9b1ea8d45364fff67b4aa71ecf67f16c497b5846ff50aaae882e71ac5e6f3ba29189d03da3ed91511074747db413a3e8f90fd9b8fa0751e8ecde29324f4fe8d9023405e33e0d07741056941f9593e8931d0c22553af6447d5c38c762e45afaa89cc11c6843e77430cea44b41fcef0ad11d08d3be1f279ee791fd3b4a8b39d2889a51a4cb2a81885ef6cab119e8de29908a0e").unwrap(),
// A default script can never be spent, intentionally
Expand Down
56 changes: 33 additions & 23 deletions base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,7 @@ use crate::{
consensus::{ConsensusManager, DomainSeparatedConsensusHasher},
transactions::{
aggregated_body::AggregateBody,
transaction_components::{
SpentOutput,
TransactionError,
TransactionInput,
TransactionKernel,
TransactionOutput,
},
transaction_components::{TransactionError, TransactionInput, TransactionKernel, TransactionOutput},
TransactionHashDomain,
},
MutablePrunedOutputMmr,
Expand Down Expand Up @@ -1268,16 +1262,18 @@ impl LMDBDatabase {
None => return Err(ChainStorageError::UnspendableInput),
},
};
if let SpentOutput::OutputData {
version: _, features, ..
} = &input.spent_output

let features = input.features()?;
if let Some(vn_reg) = features
.sidechain_feature
.as_ref()
.and_then(|f| f.validator_node_registration())
{
if let Some(validator_node_public_key) = &features.validator_node_public_key {
let read_txn = self.read_transaction()?;
let shard_key = self.get_vn_mapping(&read_txn, validator_node_public_key)?;
self.delete_validator_node(txn, validator_node_public_key, &shard_key)?;
}
let read_txn = self.read_transaction()?;
let shard_key = self.get_vn_mapping(&read_txn, &vn_reg.public_key)?;
self.delete_validator_node(txn, &vn_reg.public_key, &shard_key)?;
}

if !output_mmr.delete(index) {
return Err(ChainStorageError::InvalidOperation(format!(
"Could not delete index {} from the output MMR",
Expand All @@ -1296,9 +1292,16 @@ impl LMDBDatabase {
mmr_count
))
})?;
if let Some(validator_node_public_key) = &output.features.validator_node_public_key {

if let Some(vn_reg) = output
.features
.sidechain_feature
.as_ref()
.and_then(|f| f.validator_node_registration())
{
let shard_key = DomainSeparatedConsensusHasher::<TransactionHashDomain>::new("validator_node_root")
.chain(&validator_node_public_key.as_bytes())
// <pk, sig>
.chain(vn_reg)
.chain(&block_hash)
.finalize();

Expand All @@ -1310,7 +1313,7 @@ impl LMDBDatabase {
self.consensus_manager
.consensus_constants(header.height)
.get_validator_node_timeout(),
public_key: validator_node_public_key.clone(),
public_key: vn_reg.public_key.clone(),
};
self.insert_validator_node(txn, &validator_node)?;
}
Expand Down Expand Up @@ -1563,21 +1566,27 @@ impl LMDBDatabase {
lmdb_insert(
txn,
&self.validator_nodes,
&validator_node.public_key.to_vec(),
validator_node.public_key.as_bytes(),
validator_node,
"validator_nodes",
)?;
lmdb_insert(
txn,
&self.validator_nodes_mapping,
&validator_node.shard_key,
&validator_node.public_key.to_vec(),
&validator_node.public_key.as_bytes(),
"validator_nodes_mapping",
)
}

fn get_vn_mapping(&self, txn: &ReadTransaction<'_>, public_key: &PublicKey) -> Result<[u8; 32], ChainStorageError> {
let x: ActiveValidatorNode = lmdb_get(txn, &self.validator_nodes, &public_key.to_vec())?.unwrap();
let x: ActiveValidatorNode = lmdb_get(txn, &self.validator_nodes, public_key.as_bytes())?.ok_or_else(|| {
ChainStorageError::ValueNotFound {
entity: "ActiveValidatorNode",
field: "public_key",
value: public_key.to_hex(),
}
})?;
Ok(x.shard_key)
}

Expand All @@ -1587,8 +1596,9 @@ impl LMDBDatabase {
public_key: &PublicKey,
shard_key: &[u8; 32],
) -> Result<(), ChainStorageError> {
lmdb_delete(txn, &self.validator_nodes, &public_key.to_vec(), "validator_nodes")?;
lmdb_delete(txn, &self.validator_nodes, shard_key, "validator_nodes_mapping")
lmdb_delete(txn, &self.validator_nodes, public_key.as_bytes(), "validator_nodes")?;
lmdb_delete(txn, &self.validator_nodes, shard_key, "validator_nodes_mapping")?;
Ok(())
}

fn fetch_output_in_txn(
Expand Down
3 changes: 2 additions & 1 deletion base_layer/core/src/consensus/consensus_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,8 @@ impl ConsensusConstants {
input_version_range,
output_version_range,
kernel_version_range,
permitted_output_types: Self::current_permitted_output_types(),
// igor is the first network to support the new output types
permitted_output_types: OutputType::all(),
validator_node_timeout: 0,
}]
}
Expand Down
Loading

0 comments on commit 0fef174

Please sign in to comment.