From e3a622e14e98d18ac1ae33aeeb7a5f6eb8c1ec30 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 14 Feb 2022 11:14:24 +0200 Subject: [PATCH 1/9] feat!: add committee management utxo --- applications/tari_app_grpc/proto/types.proto | 7 +- applications/tari_app_grpc/proto/wallet.proto | 11 +++ .../src/conversions/output_features.rs | 34 ++++++- .../src-tauri/src/clients/base_node_client.rs | 8 +- .../src/clients/validator_node_client.rs | 6 +- .../src-tauri/src/clients/wallet_client.rs | 90 +++++++++++++----- .../src-tauri/src/commands/assets/mod.rs | 18 +++- .../tari_collectibles/src-tauri/src/error.rs | 9 +- .../tari_collectibles/src-tauri/src/status.rs | 8 +- .../src/automation/command_parser.rs | 4 +- .../src/automation/commands.rs | 42 +++++++-- .../src/grpc/wallet_grpc_server.rs | 79 +++++++++++----- .../src/ui/state/app_state.rs | 2 - .../tari_console_wallet/src/ui/state/tasks.rs | 2 - .../state_machine_service/state_machine.rs | 2 +- .../src/base_node/sync/rpc/sync_utxos_task.rs | 1 - base_layer/core/src/blocks/genesis_block.rs | 67 ++++++++----- .../src/chain_storage/blockchain_database.rs | 12 +++ base_layer/core/src/proto/transaction.proto | 6 ++ base_layer/core/src/proto/transaction.rs | 34 ++++++- .../core/src/transactions/aggregated_body.rs | 3 +- .../core/src/transactions/test_helpers.rs | 1 - .../committee_checkpoint_features.rs | 94 +++++++++++++++++++ .../transaction_components/mod.rs | 2 + .../transaction_components/output_features.rs | 51 +++++++++- .../output_features_version.rs | 6 +- .../transaction_components/output_flags.rs | 11 ++- .../transaction_input.rs | 1 - .../transaction_output.rs | 4 +- .../transaction_output_version.rs | 2 + .../unblinded_output.rs | 3 +- base_layer/core/src/validation/helpers.rs | 11 ++- base_layer/core/tests/helpers/nodes.rs | 2 +- .../p2p/src/services/liveness/service.rs | 1 - base_layer/wallet/src/assets/asset_manager.rs | 28 ++++++ .../wallet/src/assets/asset_manager_handle.rs | 33 +++++-- .../infrastructure/asset_manager_service.rs | 14 +++ .../wallet/src/assets/infrastructure/mod.rs | 6 ++ base_layer/wallet/src/config.rs | 1 - .../src/output_manager_service/service.rs | 1 - .../protocols/transaction_send_protocol.rs | 1 - .../wallet/src/transaction_service/service.rs | 1 - .../src/transaction_service/storage/models.rs | 2 - .../src/utxo_scanner_service/service.rs | 1 - .../uxto_scanner_service_builder.rs | 1 - base_layer/wallet/src/wallet.rs | 2 +- .../transaction_service_tests/service.rs | 1 - base_layer/wallet_ffi/src/callback_handler.rs | 2 +- clippy.toml | 1 + comms/dht/examples/memory_net/utilities.rs | 3 - comms/dht/src/actor.rs | 1 - comms/dht/src/connectivity/mod.rs | 1 - comms/dht/src/outbound/broadcast.rs | 2 - .../store_forward/saf_handler/middleware.rs | 1 - .../dht/src/store_forward/saf_handler/task.rs | 1 - comms/dht/src/store_forward/service.rs | 1 - comms/dht/src/test_utils/makers.rs | 1 - comms/dht/tests/dht.rs | 1 - comms/src/connection_manager/dialer.rs | 2 - comms/src/connection_manager/listener.rs | 2 - comms/src/connection_manager/manager.rs | 1 - .../src/connection_manager/peer_connection.rs | 2 - comms/src/peer_manager/peer.rs | 2 +- comms/src/peer_manager/peer_storage.rs | 2 +- comms/src/protocol/messaging/protocol.rs | 1 - comms/src/protocol/rpc/client/mod.rs | 1 - comms/src/tor/hidden_service/controller.rs | 1 - dan_layer/core/src/workers/states/prepare.rs | 1 - 68 files changed, 580 insertions(+), 176 deletions(-) create mode 100644 base_layer/core/src/transactions/transaction_components/committee_checkpoint_features.rs diff --git a/applications/tari_app_grpc/proto/types.proto b/applications/tari_app_grpc/proto/types.proto index a9eeea1105..f6f5b2ba61 100644 --- a/applications/tari_app_grpc/proto/types.proto +++ b/applications/tari_app_grpc/proto/types.proto @@ -204,7 +204,7 @@ message TransactionOutput { uint32 version = 9; } -// Options for UTXO's +// Options for UTXOs message OutputFeatures { // Flags are the feature flags that differentiate between outputs, eg Coinbase all of which has different rules uint32 flags = 1; @@ -225,6 +225,7 @@ message OutputFeatures { SideChainCheckpointFeatures sidechain_checkpoint = 8; // Version uint32 version = 9; + CommitteeCheckpointFeatures committee_checkpoint = 10; } message AssetOutputFeatures { @@ -249,6 +250,10 @@ message SideChainCheckpointFeatures { repeated bytes committee = 2; } +message CommitteeCheckpointFeatures { + repeated bytes committee = 1; + uint64 effective_sidechain_height = 2; +} // The components of the block or transaction. The same struct can be used for either, since in Mimblewimble, // cut-through means that blocks and transactions have the same structure. The inputs, outputs and kernels should diff --git a/applications/tari_app_grpc/proto/wallet.proto b/applications/tari_app_grpc/proto/wallet.proto index edb4a6957d..cfb4dd8c13 100644 --- a/applications/tari_app_grpc/proto/wallet.proto +++ b/applications/tari_app_grpc/proto/wallet.proto @@ -70,6 +70,7 @@ service Wallet { rpc CreateInitialAssetCheckpoint(CreateInitialAssetCheckpointRequest) returns (CreateInitialAssetCheckpointResponse); // TODO: Needs a better name pls rpc CreateFollowOnAssetCheckpoint(CreateFollowOnAssetCheckpointRequest) returns (CreateFollowOnAssetCheckpointResponse); + rpc CreateCommitteeCheckpoint(CreateCommitteeCheckpointRequest) returns (CreateCommitteeCheckpointResponse); rpc GetOwnedAssets(Empty) returns (GetOwnedAssetsResponse); @@ -280,6 +281,16 @@ message CreateFollowOnAssetCheckpointResponse { } +message CreateCommitteeCheckpointRequest { + bytes asset_public_key = 1; + repeated bytes committee = 2; + uint64 effective_sidechain_height = 3; +} + +message CreateCommitteeCheckpointResponse { + +} + message GetOwnedAssetsResponse { repeated Asset assets = 1; } diff --git a/applications/tari_app_grpc/src/conversions/output_features.rs b/applications/tari_app_grpc/src/conversions/output_features.rs index 7c0a009248..c9a1fb5899 100644 --- a/applications/tari_app_grpc/src/conversions/output_features.rs +++ b/applications/tari_app_grpc/src/conversions/output_features.rs @@ -28,6 +28,7 @@ use tari_common_types::{ }; use tari_core::transactions::transaction_components::{ AssetOutputFeatures, + CommitteeCheckpointFeatures, MintNonFungibleFeatures, OutputFeatures, OutputFeaturesVersion, @@ -66,7 +67,8 @@ impl TryFrom for OutputFeatures { parent_public_key, features.asset.map(|a| a.try_into()).transpose()?, features.mint_non_fungible.map(|m| m.try_into()).transpose()?, - features.sidechain_checkpoint.map(|m| m.try_into()).transpose()?, + features.sidechain_checkpoint.map(|s| s.try_into()).transpose()?, + features.committee_checkpoint.map(|c| c.try_into()).transpose()?, )) } } @@ -86,6 +88,7 @@ impl From for grpc::OutputFeatures { mint_non_fungible: features.mint_non_fungible.map(|m| m.into()), sidechain_checkpoint: features.sidechain_checkpoint.map(|m| m.into()), version: features.version as u32, + committee_checkpoint: features.committee_checkpoint.map(|c| c.into()), } } } @@ -184,3 +187,32 @@ impl TryFrom for SideChainCheckpointFeatures Ok(Self { merkle_root, committee }) } } + +impl From for grpc::CommitteeCheckpointFeatures { + fn from(value: CommitteeCheckpointFeatures) -> Self { + Self { + committee: value.committee.iter().map(|c| c.as_bytes().to_vec()).collect(), + effective_sidechain_height: value.effective_sidechain_height, + } + } +} + +impl TryFrom for CommitteeCheckpointFeatures { + type Error = String; + + fn try_from(value: grpc::CommitteeCheckpointFeatures) -> Result { + let committee = value + .committee + .iter() + .map(|c| { + PublicKey::from_bytes(c).map_err(|err| format!("committee member was not a valid public key: {}", err)) + }) + .collect::>()?; + let effective_sidechain_height = value.effective_sidechain_height; + + Ok(Self { + committee, + effective_sidechain_height, + }) + } +} diff --git a/applications/tari_collectibles/src-tauri/src/clients/base_node_client.rs b/applications/tari_collectibles/src-tauri/src/clients/base_node_client.rs index f620a27fef..174aca4a1b 100644 --- a/applications/tari_collectibles/src-tauri/src/clients/base_node_client.rs +++ b/applications/tari_collectibles/src-tauri/src/clients/base_node_client.rs @@ -37,7 +37,7 @@ impl BaseNodeClient { pub async fn connect(endpoint: String) -> Result { let client = grpc::base_node_client::BaseNodeClient::connect(endpoint.clone()) .await - .map_err(|err| CollectiblesError::ClientConnectionError { + .map_err(|err| CollectiblesError::ClientConnection { client: "wallet", address: endpoint, error: err.to_string(), @@ -57,14 +57,14 @@ impl BaseNodeClient { .list_asset_registrations(request) .await .map(|response| response.into_inner()) - .map_err(|source| CollectiblesError::ClientRequestError { + .map_err(|source| CollectiblesError::ClientRequest { request: "list_asset_registrations".to_string(), source, })?; let mut assets = vec![]; while let Some(result) = stream.next().await { - let asset = result.map_err(|source| CollectiblesError::ClientRequestError { + let asset = result.map_err(|source| CollectiblesError::ClientRequest { request: "list_asset_registrations".to_string(), source, })?; @@ -87,7 +87,7 @@ impl BaseNodeClient { .get_asset_metadata(request) .await .map(|response| response.into_inner()) - .map_err(|s| CollectiblesError::ClientRequestError { + .map_err(|s| CollectiblesError::ClientRequest { request: "get_asset_metadata".to_string(), source: s, })?; diff --git a/applications/tari_collectibles/src-tauri/src/clients/validator_node_client.rs b/applications/tari_collectibles/src-tauri/src/clients/validator_node_client.rs index 7f91653cc4..d720b7f43e 100644 --- a/applications/tari_collectibles/src-tauri/src/clients/validator_node_client.rs +++ b/applications/tari_collectibles/src-tauri/src/clients/validator_node_client.rs @@ -38,7 +38,7 @@ impl GrpcValidatorNodeClient { let s = Self { client: grpc::validator_node_client::ValidatorNodeClient::connect(endpoint.clone()) .await - .map_err(|e| CollectiblesError::ClientConnectionError { + .map_err(|e| CollectiblesError::ClientConnection { client: "validator_node", address: endpoint, error: e.to_string(), @@ -69,7 +69,7 @@ impl GrpcValidatorNodeClient { .map_err(|e| { error!(target: LOG_TARGET, "{}", e); - CollectiblesError::ClientRequestError { + CollectiblesError::ClientRequest { source: e, request: "invoke_read_method".to_string(), } @@ -100,7 +100,7 @@ impl GrpcValidatorNodeClient { .map_err(|e| { error!(target: LOG_TARGET, "{}", e); - CollectiblesError::ClientRequestError { + CollectiblesError::ClientRequest { source: e, request: "invoke_method".to_string(), } diff --git a/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs b/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs index 6e50e615b6..32e1a1894e 100644 --- a/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs +++ b/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs @@ -45,7 +45,7 @@ impl WalletClient { let dst = format!("http://{}", self.endpoint); let client = grpc::wallet_client::WalletClient::connect(dst) .await - .map_err(|err| CollectiblesError::ClientConnectionError { + .map_err(|err| CollectiblesError::ClientConnection { client: "wallet", address: self.endpoint.clone(), error: err.to_string(), @@ -55,6 +55,15 @@ impl WalletClient { Ok(()) } + fn get_inner( + &mut self, + ) -> Result<&mut grpc::wallet_client::WalletClient, CollectiblesError> + { + let inner = self.inner.as_mut().ok_or(CollectiblesError::NoConnection)?; + + Ok(inner) + } + pub async fn register_asset( &mut self, name: String, @@ -64,7 +73,7 @@ impl WalletClient { template_ids_implemented: Vec, template_parameters: Vec, ) -> Result { - let inner = self.inner.as_mut().unwrap(); + let inner = self.get_inner()?; let request = RegisterAssetRequest { name, public_key: public_key.as_bytes().into(), @@ -73,12 +82,14 @@ impl WalletClient { image, template_parameters, }; - let result = inner.register_asset(request).await.map_err(|error| { - CollectiblesError::ClientRequestError { - request: "register_asset".to_string(), - source: error, - } - })?; + let result = + inner + .register_asset(request) + .await + .map_err(|error| CollectiblesError::ClientRequest { + request: "register_asset".to_string(), + source: error, + })?; debug!(target: LOG_TARGET, "result {:?}", result); Ok(result.into_inner().public_key.to_hex()) } @@ -86,37 +97,36 @@ impl WalletClient { pub async fn list_owned_assets( &mut self, ) -> Result { - let inner = self.inner.as_mut().unwrap(); + let inner = self.get_inner()?; let request = grpc::Empty {}; - let result = inner.get_owned_assets(request).await.map_err(|source| { - CollectiblesError::ClientRequestError { - request: "get_owned_assets".to_string(), - source, - } - })?; + let result = + inner + .get_owned_assets(request) + .await + .map_err(|source| CollectiblesError::ClientRequest { + request: "get_owned_assets".to_string(), + source, + })?; debug!(target: LOG_TARGET, "result {:?}", result); Ok(result.into_inner()) } pub async fn create_initial_asset_checkpoint( &mut self, - asset_public_key: String, + asset_public_key: &str, merkle_root: Vec, - committee: Vec, ) -> Result { - let inner = self.inner.as_mut().unwrap(); + let inner = self.get_inner()?; + let committee = vec![]; let request = grpc::CreateInitialAssetCheckpointRequest { - asset_public_key: Vec::from_hex(&asset_public_key).unwrap(), + asset_public_key: Vec::from_hex(asset_public_key)?, merkle_root, - committee: committee - .iter() - .map(|s| Vec::from_hex(s).unwrap()) - .collect(), + committee, }; let result = inner .create_initial_asset_checkpoint(request) .await - .map_err(|source| CollectiblesError::ClientRequestError { + .map_err(|source| CollectiblesError::ClientRequest { request: "create_initial_asset_checkpoint".to_string(), source, })?; @@ -124,13 +134,41 @@ impl WalletClient { Ok(result.into_inner()) } + pub async fn create_committee_checkpoint( + &mut self, + asset_public_key: &str, + committee: Vec, + effective_sidechain_height: u64, + ) -> Result { + let inner = self.get_inner()?; + let committee = committee + .iter() + .map(|s| Vec::from_hex(s)) + .collect::, _>>()?; + + let request = grpc::CreateCommitteeCheckpointRequest { + asset_public_key: Vec::from_hex(asset_public_key)?, + committee, + effective_sidechain_height, + }; + let result = inner + .create_committee_checkpoint(request) + .await + .map_err(|source| CollectiblesError::ClientRequest { + request: "create_committee_checkpoint".to_string(), + source, + })?; + debug!(target: LOG_TARGET, "result {:?}", result); + Ok(result.into_inner()) + } + pub async fn get_unspent_amounts( &mut self, ) -> Result { - let inner = self.inner.as_mut().unwrap(); + let inner = self.get_inner()?; let request = grpc::Empty {}; let result = inner.get_unspent_amounts(request).await.map_err(|source| { - CollectiblesError::ClientRequestError { + CollectiblesError::ClientRequest { request: "get_unspent_amounts".to_string(), source, } diff --git a/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs b/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs index 0871aec587..3c0f8ea258 100644 --- a/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs +++ b/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs @@ -237,21 +237,29 @@ pub(crate) async fn assets_list_registered_assets( #[tauri::command] pub(crate) async fn assets_create_initial_checkpoint( - asset_pub_key: String, + asset_public_key: String, committee: Vec, state: tauri::State<'_, ConcurrentAppState>, ) -> Result<(), Status> { let mmr = MerkleMountainRange::::new(MemBackendVec::new()); - let root = mmr.get_merkle_root().unwrap(); + let merkle_root = mmr.get_merkle_root().unwrap(); let mut client = state.create_wallet_client().await; client.connect().await?; + // todo: check for enough utxos first + + // create asset reg checkpoint client - .create_initial_asset_checkpoint(asset_pub_key, root, committee) - .await - .unwrap(); + .create_initial_asset_checkpoint(&asset_public_key, merkle_root) + .await?; + + // create committee checkpoint + // TODO: effective sidechain height... + client + .create_committee_checkpoint(&asset_public_key, committee, 0) + .await?; Ok(()) } diff --git a/applications/tari_collectibles/src-tauri/src/error.rs b/applications/tari_collectibles/src-tauri/src/error.rs index 21f99cee27..8e99360db4 100644 --- a/applications/tari_collectibles/src-tauri/src/error.rs +++ b/applications/tari_collectibles/src-tauri/src/error.rs @@ -20,16 +20,21 @@ // 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 tari_utilities::hex::HexError; use tonic::Status; #[derive(Debug, thiserror::Error)] pub enum CollectiblesError { #[error("No connection to {client}. Is it running with grpc on '{address}' ? Error: {error}")] - ClientConnectionError { + ClientConnection { client: &'static str, address: String, error: String, }, #[error("Error invoking operation: {request}: {source}")] - ClientRequestError { request: String, source: Status }, + ClientRequest { request: String, source: Status }, + #[error("Error trying to use wallet client before calling connect()")] + NoConnection, + #[error("Error converting from Hex to Public Key")] + Hex(#[from] HexError), } diff --git a/applications/tari_collectibles/src-tauri/src/status.rs b/applications/tari_collectibles/src-tauri/src/status.rs index 34a03721cc..188e9e2582 100644 --- a/applications/tari_collectibles/src-tauri/src/status.rs +++ b/applications/tari_collectibles/src-tauri/src/status.rs @@ -74,17 +74,17 @@ impl From for Status { StorageError::DieselError { source } => match source { Error::NotFound => Self::NotFound { code: 404, - message: format!("Not found:{}", source), + message: format!("Not found: {}", source), entity: "Unknown".to_string(), }, _ => Self::Internal { code: 502, - message: format!("Internal diesel storage error:{}", source), + message: format!("Internal diesel storage error: {}", source), }, }, _ => Self::Internal { code: 501, - message: format!("Internal storage error:{}", source), + message: format!("Internal storage error: {}", source), }, } } @@ -121,7 +121,7 @@ impl From for Status { fn from(ce: CollectiblesError) -> Self { Self::Internal { code: 504, - message: format!("Error:{}", ce), + message: format!("Error: {}", ce), } } } diff --git a/applications/tari_console_wallet/src/automation/command_parser.rs b/applications/tari_console_wallet/src/automation/command_parser.rs index d5e53ff7f6..37ef95d44b 100644 --- a/applications/tari_console_wallet/src/automation/command_parser.rs +++ b/applications/tari_console_wallet/src/automation/command_parser.rs @@ -65,6 +65,7 @@ impl Display for ParsedCommand { RegisterAsset => "register-asset", MintTokens => "mint-tokens", CreateInitialCheckpoint => "create-initial-checkpoint", + CreateCommitteeCheckpoint => "create-committee-checkpoint", }; let args = self @@ -140,7 +141,8 @@ pub fn parse_command(command: &str) -> Result { RegisterAsset => parser_builder(args).text().build()?, // mint-tokens pub_key nft_id1 nft_id2 MintTokens => parser_builder(args).pub_key().text_array().build()?, - CreateInitialCheckpoint => parser_builder(args).pub_key().text().pub_key_array().build()?, + CreateInitialCheckpoint => parser_builder(args).pub_key().text().build()?, + CreateCommitteeCheckpoint => parser_builder(args).pub_key().pub_key_array().build()?, }; Ok(ParsedCommand { command, args }) diff --git a/applications/tari_console_wallet/src/automation/commands.rs b/applications/tari_console_wallet/src/automation/commands.rs index f9065b5aa9..37cf162ce5 100644 --- a/applications/tari_console_wallet/src/automation/commands.rs +++ b/applications/tari_console_wallet/src/automation/commands.rs @@ -94,6 +94,7 @@ pub enum WalletCommand { RegisterAsset, MintTokens, CreateInitialCheckpoint, + CreateCommitteeCheckpoint, } #[derive(Debug, EnumString, PartialEq, Clone)] @@ -848,7 +849,7 @@ pub async fn command_runner( }, CreateInitialCheckpoint => { println!("Creating Initial Checkpoint for Asset"); - let public_key = match parsed.args[0] { + let asset_public_key = match parsed.args[0] { ParsedArgument::PublicKey(ref key) => Ok(key.clone()), _ => Err(CommandError::Argument), }?; @@ -864,7 +865,24 @@ pub async fn command_runner( _ => return Err(CommandError::Argument), }; - let committee: Vec = parsed.args[2..] + let message = format!("Initial asset checkpoint for {}", asset_public_key); + + let mut asset_manager = wallet.asset_manager.clone(); + let (tx_id, transaction) = asset_manager + .create_initial_asset_checkpoint(&asset_public_key, merkle_root) + .await?; + let _result = transaction_service + .submit_transaction(tx_id, transaction, 0.into(), message) + .await?; + }, + CreateCommitteeCheckpoint => { + println!("Creating Committee Checkpoint for Asset"); + let asset_public_key = match parsed.args[0] { + ParsedArgument::PublicKey(ref key) => Ok(key.clone()), + _ => Err(CommandError::Argument), + }?; + + let committee_public_keys: Vec = parsed.args[1..] .iter() .map(|pk| match pk { ParsedArgument::PublicKey(ref key) => Ok(key.clone()), @@ -872,17 +890,23 @@ pub async fn command_runner( }) .collect::>()?; + let num_members = committee_public_keys.len(); + if num_members < 1 { + return Err(CommandError::Config("Committee has no members!".into())); + } + let message = format!( + "Committee checkpoint with {} members for {}", + num_members, asset_public_key + ); + let mut asset_manager = wallet.asset_manager.clone(); + // todo: effective sidechain height... let (tx_id, transaction) = asset_manager - .create_initial_asset_checkpoint(&public_key, merkle_root, &committee) + .create_committee_checkpoint(&asset_public_key, &committee_public_keys, 0) .await?; + let _result = transaction_service - .submit_transaction( - tx_id, - transaction, - 0.into(), - "test initial asset checkpoint transaction".to_string(), - ) + .submit_transaction(tx_id, transaction, 0.into(), message) .await?; }, } diff --git a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs index 68fe030250..7ea076236a 100644 --- a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs +++ b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs @@ -36,6 +36,8 @@ use tari_app_grpc::{ ClaimShaAtomicSwapResponse, CoinSplitRequest, CoinSplitResponse, + CreateCommitteeCheckpointRequest, + CreateCommitteeCheckpointResponse, CreateFollowOnAssetCheckpointRequest, CreateFollowOnAssetCheckpointResponse, CreateInitialAssetCheckpointRequest, @@ -631,8 +633,9 @@ impl wallet_server::Wallet for WalletGrpcServer { }) .next() .unwrap(); + let message = format!("Asset registration for {}", asset_public_key); let _result = transaction_service - .submit_transaction(tx_id, transaction, 0.into(), "register asset transaction".to_string()) + .submit_transaction(tx_id, transaction, 0.into(), message) .await .map_err(|e| Status::internal(e.to_string()))?; Ok(Response::new(RegisterAssetResponse { @@ -671,23 +674,18 @@ impl wallet_server::Wallet for WalletGrpcServer { let asset_public_key = PublicKey::from_bytes(message.asset_public_key.as_slice()) .map_err(|e| Status::invalid_argument(format!("Asset public key was not a valid pub key:{}", e)))?; - let committee_public_keys: Vec = message - .committee - .iter() - .map(|c| PublicKey::from_bytes(c.as_slice())) - .collect::>() - .map_err(|err| Status::invalid_argument(format!("Committee did not contain valid pub keys:{}", err)))?; let merkle_root = copy_into_fixed_array(&message.merkle_root) .map_err(|_| Status::invalid_argument("Merkle root has an incorrect length"))?; let (tx_id, transaction) = asset_manager - .create_initial_asset_checkpoint(&asset_public_key, merkle_root, committee_public_keys.as_slice()) + .create_initial_asset_checkpoint(&asset_public_key, merkle_root) .await .map_err(|e| Status::internal(e.to_string()))?; + let message = format!("Initial asset checkpoint for {}", asset_public_key); let _result = transaction_service - .submit_transaction(tx_id, transaction, 0.into(), "Asset checkpoint".to_string()) + .submit_transaction(tx_id, transaction, 0.into(), message) .await .map_err(|e| Status::internal(e.to_string()))?; @@ -704,36 +702,59 @@ impl wallet_server::Wallet for WalletGrpcServer { let asset_public_key = PublicKey::from_bytes(message.asset_public_key.as_slice()) .map_err(|e| Status::invalid_argument(format!("Asset public key was not a valid pub key:{}", e)))?; - let committee_public_keys: Vec = message - .next_committee - .iter() - .map(|c| PublicKey::from_bytes(c.as_slice())) - .collect::>() - .map_err(|err| { - Status::invalid_argument(format!("Next committee did not contain valid pub keys:{}", err)) - })?; let merkle_root = copy_into_fixed_array(&message.merkle_root) .map_err(|_| Status::invalid_argument("Incorrect merkle root length"))?; let (tx_id, transaction) = asset_manager - .create_follow_on_asset_checkpoint( - &asset_public_key, - message.unique_id.as_slice(), - merkle_root, - committee_public_keys.as_slice(), - ) + .create_follow_on_asset_checkpoint(&asset_public_key, message.unique_id.as_slice(), merkle_root) .await .map_err(|e| Status::internal(e.to_string()))?; + let message = format!("Asset state checkpoint for {}", asset_public_key); let _result = transaction_service - .submit_transaction(tx_id, transaction, 0.into(), "Follow on asset checkpoint".to_string()) + .submit_transaction(tx_id, transaction, 0.into(), message) .await .map_err(|e| Status::internal(e.to_string()))?; Ok(Response::new(CreateFollowOnAssetCheckpointResponse {})) } + async fn create_committee_checkpoint( + &self, + request: Request, + ) -> Result, Status> { + let mut asset_manager = self.wallet.asset_manager.clone(); + let mut transaction_service = self.wallet.transaction_service.clone(); + let message = request.into_inner(); + + let asset_public_key = PublicKey::from_bytes(message.asset_public_key.as_slice()) + .map_err(|e| Status::invalid_argument(format!("Asset public key was not a valid pub key:{}", e)))?; + let committee_public_keys: Vec = message + .committee + .iter() + .map(|c| PublicKey::from_bytes(c.as_slice())) + .collect::>() + .map_err(|err| Status::invalid_argument(format!("Committee did not contain valid pub keys:{}", err)))?; + let effective_sidechain_height = message.effective_sidechain_height; + + let (tx_id, transaction) = asset_manager + .create_committee_checkpoint(&asset_public_key, &committee_public_keys, effective_sidechain_height) + .await + .map_err(|e| Status::internal(e.to_string()))?; + + let message = format!( + "Committee checkpoint for asset {} with effective sidechain height {}", + asset_public_key, effective_sidechain_height + ); + let _result = transaction_service + .submit_transaction(tx_id, transaction, 0.into(), message) + .await + .map_err(|e| Status::internal(e.to_string()))?; + + Ok(Response::new(CreateCommitteeCheckpointResponse {})) + } + async fn mint_tokens(&self, request: Request) -> Result, Status> { let mut asset_manager = self.wallet.asset_manager.clone(); let mut transaction_service = self.wallet.transaction_service.clone(); @@ -760,14 +781,20 @@ impl wallet_server::Wallet for WalletGrpcServer { .await .map_err(|e| Status::internal(e.to_string()))?; - let owner_commitments = transaction + let owner_commitments: Vec> = transaction .body .outputs() .iter() .filter_map(|o| o.features.unique_id.as_ref().map(|_| o.commitment.to_vec())) .collect(); + + let message = format!( + "Minting {} tokens for asset {}", + owner_commitments.len(), + asset_public_key + ); let _result = transaction_service - .submit_transaction(tx_id, transaction, 0.into(), "test mint transaction".to_string()) + .submit_transaction(tx_id, transaction, 0.into(), message) .await .map_err(|e| Status::internal(e.to_string()))?; diff --git a/applications/tari_console_wallet/src/ui/state/app_state.rs b/applications/tari_console_wallet/src/ui/state/app_state.rs index 955762b728..86a2f703f7 100644 --- a/applications/tari_console_wallet/src/ui/state/app_state.rs +++ b/applications/tari_console_wallet/src/ui/state/app_state.rs @@ -275,7 +275,6 @@ impl AppState { Ok(()) } - #[allow(clippy::too_many_arguments)] pub async fn send_transaction( &mut self, public_key: String, @@ -308,7 +307,6 @@ impl AppState { Ok(()) } - #[allow(clippy::too_many_arguments)] pub async fn send_one_sided_transaction( &mut self, public_key: String, diff --git a/applications/tari_console_wallet/src/ui/state/tasks.rs b/applications/tari_console_wallet/src/ui/state/tasks.rs index 1bf1875d0c..3d18cbea42 100644 --- a/applications/tari_console_wallet/src/ui/state/tasks.rs +++ b/applications/tari_console_wallet/src/ui/state/tasks.rs @@ -30,7 +30,6 @@ use crate::ui::{state::UiTransactionSendStatus, UiError}; const LOG_TARGET: &str = "wallet::console_wallet::tasks "; -#[allow(clippy::too_many_arguments)] pub async fn send_transaction_task( public_key: CommsPublicKey, amount: MicroTari, @@ -108,7 +107,6 @@ pub async fn send_transaction_task( } } -#[allow(clippy::too_many_arguments)] pub async fn send_one_sided_transaction_task( public_key: CommsPublicKey, amount: MicroTari, diff --git a/base_layer/core/src/base_node/state_machine_service/state_machine.rs b/base_layer/core/src/base_node/state_machine_service/state_machine.rs index df86e2b6bc..0466098687 100644 --- a/base_layer/core/src/base_node/state_machine_service/state_machine.rs +++ b/base_layer/core/src/base_node/state_machine_service/state_machine.rs @@ -110,7 +110,7 @@ pub struct BaseNodeStateMachine { impl BaseNodeStateMachine { /// Instantiate a new Base Node. - #[allow(clippy::too_many_arguments)] + pub fn new( db: AsyncBlockchainDb, local_node_interface: LocalNodeCommsInterface, diff --git a/base_layer/core/src/base_node/sync/rpc/sync_utxos_task.rs b/base_layer/core/src/base_node/sync/rpc/sync_utxos_task.rs index 22326ae14f..8c94e66634 100644 --- a/base_layer/core/src/base_node/sync/rpc/sync_utxos_task.rs +++ b/base_layer/core/src/base_node/sync/rpc/sync_utxos_task.rs @@ -128,7 +128,6 @@ where B: BlockchainBackend + 'static Ok(()) } - #[allow(clippy::too_many_arguments)] async fn start_streaming( &self, tx: &mut mpsc::Sender>, diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index f2e4f18501..6a83d62659 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -24,7 +24,15 @@ use std::sync::Arc; use chrono::DateTime; use tari_common::configuration::Network; -use tari_common_types::types::{BulletRangeProof, Commitment, PrivateKey, PublicKey, Signature, BLOCK_HASH_LENGTH}; +use tari_common_types::types::{ + BulletRangeProof, + ComSignature, + Commitment, + PrivateKey, + PublicKey, + Signature, + BLOCK_HASH_LENGTH, +}; use tari_crypto::{ script::TariScript, tari_utilities::{hash::Hashable, hex::*}, @@ -37,7 +45,16 @@ use crate::{ transactions::{ aggregated_body::AggregateBody, tari_amount::MicroTari, - transaction_components::{KernelFeatures, OutputFeatures, OutputFlags, TransactionKernel, TransactionOutput}, + transaction_components::{ + KernelFeatures, + OutputFeatures, + OutputFeaturesVersion, + OutputFlags, + TransactionKernel, + TransactionKernelVersion, + TransactionOutput, + TransactionOutputVersion, + }, }, }; @@ -220,32 +237,40 @@ fn get_dibbler_genesis_block_raw() -> Block { PublicKey::from_hex("58c2fbf8d67f16c383e7f5335eeaca3d8fa0c2b8b8027db04511c75d8f2df211").unwrap(), PrivateKey::from_hex("4bb9c5d4504672cb15dce9447801a928f771f2a6f0c4fb9f9d87a3a0aaa18300").unwrap(), ); - let mut body = AggregateBody::new( - vec![], - vec![TransactionOutput::new_current_version( + let coinbase = TransactionOutput::new( + TransactionOutputVersion::V0, OutputFeatures { - flags: OutputFlags::COINBASE_OUTPUT, - maturity: 60, - ..Default::default() + version:OutputFeaturesVersion::V0, + flags:OutputFlags::COINBASE_OUTPUT, + maturity:60, + metadata: Vec::new(), + unique_id: None, + parent_public_key: None, + asset: None, + mint_non_fungible: None, + sidechain_checkpoint: None, + committee_checkpoint: None }, Commitment::from_hex("e2b9ee8fdf05f9fa8fd7598d4568b539eef694e58cdae84c779140271a96d733 ").unwrap(), BulletRangeProof::from_hex("0c02c6d9bdbd1c21b29ee0f83bed597ed07f71a60f99ddcbc02550059c4c08020438f8fc25c69160dc6af81f84c037fc79b9f4a7baa93ab4d6ef1640356d9b575efe1f3f8b40f6c64d1a964aab215491f79738ccac1712d756607626442dda37ac30010dc663985153786cc53c865c01bfec186a803c1edb1a34efa3088ec221016a63cdbd2b58fa4c258bfbf0cff6b793ab62f5db0fb781f046effb5f4e7c0a956c2e042e3f0c16a72f20a624625fa6dc0b742e49e0158a50c8abde54834e04bb35baef0c258da30b738256549e3a2612ff89b4f6bfe82d16aa10b38daabe0df6b922717cb4b1604ab97a2a5efa4d325beb56c5419cff185d61e1a0fc9e374098bf4a10404d788141e2c77de222d68c14b421b62f300898c25487f491aff26be85e54c011e90cc96aff6b31993ce74233674fb150de929fbc259bcc7808a84432cf28bf83c2a0fbf2b47a6244fbafa02ca4f5c9d46c5380fe8eaed734f1d56e769e59800137900cb5905191bbb463cbcb4ea0a2073d716f18878ed4455d19426a2c1133bf703510bf0f1b3b70e9e5ee6fbb70a8e710fd0a4b8f37eacfdeef3df66e461f16ffdb270a7181505b1358f56578840bbfa284444c35160794f0294300ecb3fde701a3f5ed9234e4c196b93fd70633069eeb184ab53685b5324c963a7428094f0c7d4306b5da6ef5fb68d085c32adabe004bebcbf335ee8fc92e5e034edcb035872d08f139e9445539241ff9b9fbebbc0e7b248cbd97fa7c6f3d7823085893c9ced1685d69d2a7cf111f81e086927565c301d4e33639def1139bd5245a0ae9085d5ba10cdc1f89fc7a7fa95cc3aa11784ec40ebf57475ffb4f2b2042018e3dbe905ebd5d0ebe533f36f43f709110372c94258a59e53c9b319adca30c8e9f4f92d5937f994ff36a5bb38a15682187dc8734162f45e169a97a36fb5a05").unwrap(), - // For genesis block: A default script can never be spent, intentionally + // A default script can never be spent, intentionally TariScript::default(), - // Script offset never checked for coinbase, thus can use default - Default::default(), + // The Sender offset public key is not checked for coinbase outputs + PublicKey::default(), // For genesis block: Metadata signature will never be checked - Default::default(), - Default::default() - )], - vec![TransactionKernel::new_current_version( - KernelFeatures::COINBASE_KERNEL, - MicroTari(0), - 0, - Commitment::from_hex("0e834379ebeff1bde0513800c73ac412afdadbb101fee7a97dc7ac5d1296017f").unwrap(), - excess_sig, - )], + ComSignature::default(), + // Covenant + Covenant::default() + ); + let kernel = TransactionKernel::new( + TransactionKernelVersion::V0, + KernelFeatures::COINBASE_KERNEL, + MicroTari(0), + 0, + Commitment::from_hex("0e834379ebeff1bde0513800c73ac412afdadbb101fee7a97dc7ac5d1296017f").unwrap(), + excess_sig, ); + let mut body = AggregateBody::new(vec![], vec![coinbase], vec![kernel]); body.sort(); // set genesis timestamp let genesis = DateTime::parse_from_rfc2822("25 Jan 2022 16:00:00 +0200").unwrap(); diff --git a/base_layer/core/src/chain_storage/blockchain_database.rs b/base_layer/core/src/chain_storage/blockchain_database.rs index 53366d21bf..99febacd43 100644 --- a/base_layer/core/src/chain_storage/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/blockchain_database.rs @@ -1175,6 +1175,18 @@ pub struct MmrRoots { pub output_mmr_size: u64, } +impl std::fmt::Display for MmrRoots { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "MMR Roots")?; + writeln!(f, "Input MR : {}", &self.input_mr.to_hex())?; + writeln!(f, "Witness MR : {}", &self.witness_mr.to_hex())?; + writeln!(f, "Kernel MR : {}", &self.kernel_mr.to_hex())?; + writeln!(f, "Kernel MMR Size : {}", &self.kernel_mmr_size)?; + writeln!(f, "Output MR : {}", &self.output_mr.to_hex())?; + writeln!(f, "Output MMR Size : {}", &self.output_mmr_size) + } +} + pub fn calculate_mmr_roots(db: &T, block: &Block) -> Result { let header = &block.header; let body = &block.body; diff --git a/base_layer/core/src/proto/transaction.proto b/base_layer/core/src/proto/transaction.proto index 1754182e39..813e47dd8c 100644 --- a/base_layer/core/src/proto/transaction.proto +++ b/base_layer/core/src/proto/transaction.proto @@ -95,6 +95,7 @@ message OutputFeatures { SideChainCheckpointFeatures sidechain_checkpoint = 8; // Version uint32 version = 9; + CommitteeCheckpointFeatures committee_checkpoint = 10; } message AssetOutputFeatures { @@ -118,6 +119,11 @@ message SideChainCheckpointFeatures { bytes merkle_root = 1; repeated bytes committee = 2; } + +message CommitteeCheckpointFeatures { + repeated bytes committee = 1; + uint64 effective_sidechain_height = 2; +} // The components of the block or transaction. The same struct can be used for either, since in Mimblewimble, // cut-through means that blocks and transactions have the same structure. The inputs, outputs and kernels should // be sorted by their Blake2b-256bit digest hash diff --git a/base_layer/core/src/proto/transaction.rs b/base_layer/core/src/proto/transaction.rs index af4986efc3..923ca70c94 100644 --- a/base_layer/core/src/proto/transaction.rs +++ b/base_layer/core/src/proto/transaction.rs @@ -42,6 +42,7 @@ use crate::{ tari_amount::MicroTari, transaction_components::{ AssetOutputFeatures, + CommitteeCheckpointFeatures, KernelFeatures, MintNonFungibleFeatures, OutputFeatures, @@ -300,7 +301,8 @@ impl TryFrom for OutputFeatures { Some(m) => Some(m.try_into()?), None => None, }, - features.sidechain_checkpoint.map(|a| a.try_into()).transpose()?, + features.sidechain_checkpoint.map(|s| s.try_into()).transpose()?, + features.committee_checkpoint.map(|c| c.try_into()).transpose()?, )) } } @@ -318,8 +320,9 @@ impl From for proto::types::OutputFeatures { .unwrap_or_default(), asset: features.asset.map(|a| a.into()), mint_non_fungible: features.mint_non_fungible.map(|m| m.into()), - sidechain_checkpoint: features.sidechain_checkpoint.map(|m| m.into()), + sidechain_checkpoint: features.sidechain_checkpoint.map(|s| s.into()), version: features.version as u32, + committee_checkpoint: features.committee_checkpoint.map(|c| c.into()), } } } @@ -426,6 +429,33 @@ impl From for proto::types::SideChainCheckpointFeat } } +impl TryFrom for CommitteeCheckpointFeatures { + type Error = String; + + fn try_from(value: proto::types::CommitteeCheckpointFeatures) -> Result { + let committee = value + .committee + .into_iter() + .map(|c| PublicKey::from_bytes(&c).map_err(|err| format!("{:?}", err))) + .collect::>()?; + let effective_sidechain_height = value.effective_sidechain_height; + + Ok(Self { + committee, + effective_sidechain_height, + }) + } +} + +impl From for proto::types::CommitteeCheckpointFeatures { + fn from(value: CommitteeCheckpointFeatures) -> Self { + Self { + committee: value.committee.into_iter().map(|c| c.as_bytes().to_vec()).collect(), + effective_sidechain_height: value.effective_sidechain_height, + } + } +} + //---------------------------------- AggregateBody --------------------------------------------// impl TryFrom for AggregateBody { diff --git a/base_layer/core/src/transactions/aggregated_body.rs b/base_layer/core/src/transactions/aggregated_body.rs index 53b583276c..afab54bff0 100644 --- a/base_layer/core/src/transactions/aggregated_body.rs +++ b/base_layer/core/src/transactions/aggregated_body.rs @@ -339,7 +339,7 @@ impl AggregateBody { /// This function does NOT check that inputs come from the UTXO set /// The reward is the total amount of Tari rewarded for this block (block reward + total fees), this should be 0 /// for a transaction - #[allow(clippy::too_many_arguments)] + pub fn validate_internal_consistency( &self, tx_offset: &BlindingFactor, @@ -496,6 +496,7 @@ impl AggregateBody { self.sorted } + /// Lists the number of inputs, outputs, and kernels in the block pub fn to_counts_string(&self) -> String { format!( "{} input(s), {} output(s), {} kernel(s)", diff --git a/base_layer/core/src/transactions/test_helpers.rs b/base_layer/core/src/transactions/test_helpers.rs index 39349a54f9..dab1cb233d 100644 --- a/base_layer/core/src/transactions/test_helpers.rs +++ b/base_layer/core/src/transactions/test_helpers.rs @@ -388,7 +388,6 @@ pub fn create_tx( (tx, inputs, outputs.into_iter().map(|(utxo, _)| utxo).collect()) } -#[allow(clippy::too_many_arguments)] pub fn create_unblinded_txos( amount: MicroTari, input_count: usize, diff --git a/base_layer/core/src/transactions/transaction_components/committee_checkpoint_features.rs b/base_layer/core/src/transactions/transaction_components/committee_checkpoint_features.rs new file mode 100644 index 0000000000..3828dfa165 --- /dev/null +++ b/base_layer/core/src/transactions/transaction_components/committee_checkpoint_features.rs @@ -0,0 +1,94 @@ +// Copyright 2021. 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::io::{Error, Read, Write}; + +use integer_encoding::VarInt; +use serde::{Deserialize, Serialize}; +use tari_common_types::types::PublicKey; +use tari_crypto::keys::PublicKey as PublicKeyTrait; + +use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized, MaxSizeVec}; + +#[derive(Debug, Clone, Hash, PartialEq, Deserialize, Serialize, Eq)] +pub struct CommitteeCheckpointFeatures { + pub committee: Vec, + pub effective_sidechain_height: u64, +} + +impl ConsensusEncoding for CommitteeCheckpointFeatures { + fn consensus_encode(&self, writer: &mut W) -> Result { + let mut written = self.committee.consensus_encode(writer)?; + written += self.effective_sidechain_height.consensus_encode(writer)?; + Ok(written) + } +} + +impl ConsensusEncodingSized for CommitteeCheckpointFeatures { + fn consensus_encode_exact_size(&self) -> usize { + self.committee.len().required_space() + + self.committee.len() * PublicKey::key_length() + + self.effective_sidechain_height.required_space() + } +} + +impl ConsensusDecoding for CommitteeCheckpointFeatures { + fn consensus_decode(reader: &mut R) -> Result { + const MAX_COMMITTEE_KEYS: usize = 50; + let committee = MaxSizeVec::::consensus_decode(reader)?; + let effective_sidechain_height = u64::consensus_decode(reader)?; + + Ok(Self { + committee: committee.into(), + effective_sidechain_height, + }) + } +} + +#[cfg(test)] +mod test { + use std::{io::ErrorKind, iter}; + + use super::*; + use crate::consensus::check_consensus_encoding_correctness; + + #[test] + fn it_encodes_and_decodes_correctly() { + let subject = CommitteeCheckpointFeatures { + committee: iter::repeat_with(PublicKey::default).take(50).collect(), + effective_sidechain_height: 123, + }; + + check_consensus_encoding_correctness(subject).unwrap(); + } + + #[test] + fn it_fails_for_too_many_committee_pks() { + let subject = CommitteeCheckpointFeatures { + committee: iter::repeat_with(PublicKey::default).take(51).collect(), + effective_sidechain_height: 321, + }; + + let err = check_consensus_encoding_correctness(subject).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + } +} diff --git a/base_layer/core/src/transactions/transaction_components/mod.rs b/base_layer/core/src/transactions/transaction_components/mod.rs index 5f55585f9d..c9448e18b2 100644 --- a/base_layer/core/src/transactions/transaction_components/mod.rs +++ b/base_layer/core/src/transactions/transaction_components/mod.rs @@ -25,6 +25,7 @@ pub use asset_output_features::AssetOutputFeatures; use blake2::Digest; +pub use committee_checkpoint_features::CommitteeCheckpointFeatures; pub use error::TransactionError; pub use full_rewind_result::FullRewindResult; pub use kernel_builder::KernelBuilder; @@ -51,6 +52,7 @@ pub use unblinded_output::UnblindedOutput; pub use unblinded_output_builder::UnblindedOutputBuilder; mod asset_output_features; +mod committee_checkpoint_features; mod error; mod full_rewind_result; mod kernel_builder; diff --git a/base_layer/core/src/transactions/transaction_components/output_features.rs b/base_layer/core/src/transactions/transaction_components/output_features.rs index 647c9890de..d0e40c6f3d 100644 --- a/base_layer/core/src/transactions/transaction_components/output_features.rs +++ b/base_layer/core/src/transactions/transaction_components/output_features.rs @@ -37,6 +37,7 @@ use crate::{ consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized, MaxSizeBytes}, transactions::transaction_components::{ AssetOutputFeatures, + CommitteeCheckpointFeatures, MintNonFungibleFeatures, OutputFlags, SideChainCheckpointFeatures, @@ -59,10 +60,10 @@ pub struct OutputFeatures { pub asset: Option, pub mint_non_fungible: Option, pub sidechain_checkpoint: Option, + pub committee_checkpoint: Option, } impl OutputFeatures { - #[allow(clippy::too_many_arguments)] pub fn new( version: OutputFeaturesVersion, flags: OutputFlags, @@ -73,6 +74,7 @@ impl OutputFeatures { asset: Option, mint_non_fungible: Option, sidechain_checkpoint: Option, + committee_checkpoint: Option, ) -> OutputFeatures { OutputFeatures { version, @@ -84,10 +86,10 @@ impl OutputFeatures { asset, mint_non_fungible, sidechain_checkpoint, + committee_checkpoint, } } - #[allow(clippy::too_many_arguments)] pub fn new_current_version( flags: OutputFlags, maturity: u64, @@ -97,6 +99,7 @@ impl OutputFeatures { asset: Option, mint_non_fungible: Option, sidechain_checkpoint: Option, + committee_checkpoint: Option, ) -> OutputFeatures { OutputFeatures::new( OutputFeaturesVersion::get_current_version(), @@ -108,6 +111,7 @@ impl OutputFeatures { asset, mint_non_fungible, sidechain_checkpoint, + committee_checkpoint, ) } @@ -198,6 +202,29 @@ impl OutputFeatures { } } + pub fn for_committee( + parent_public_key: PublicKey, + unique_id: Vec, + committee: Vec, + effective_sidechain_height: u64, + is_initial: bool, + ) -> OutputFeatures { + Self { + flags: if is_initial { + OutputFlags::COMMITTEE_CHECKPOINT | OutputFlags::MINT_NON_FUNGIBLE + } else { + OutputFlags::COMMITTEE_CHECKPOINT + }, + committee_checkpoint: Some(CommitteeCheckpointFeatures { + committee, + effective_sidechain_height, + }), + parent_public_key: Some(parent_public_key), + unique_id: Some(unique_id), + ..Default::default() + } + } + pub fn unique_asset_id(&self) -> Option<&[u8]> { self.unique_id.as_deref() } @@ -226,6 +253,12 @@ impl ConsensusEncoding for OutputFeatures { written += self.mint_non_fungible.consensus_encode(writer)?; written += self.sidechain_checkpoint.consensus_encode(writer)?; written += self.metadata.consensus_encode(writer)?; + match self.version { + OutputFeaturesVersion::V0 => (), + OutputFeaturesVersion::V1 => { + written += self.committee_checkpoint.consensus_encode(writer)?; + }, + } Ok(written) } } @@ -248,6 +281,12 @@ impl ConsensusDecoding for OutputFeatures { as ConsensusDecoding>::consensus_decode(reader)?; const MAX_METADATA_SIZE: usize = 1024; let metadata = as ConsensusDecoding>::consensus_decode(reader)?; + let committee_checkpoint = match version { + OutputFeaturesVersion::V0 => None, + OutputFeaturesVersion::V1 => { + as ConsensusDecoding>::consensus_decode(reader)? + }, + }; Ok(Self { version, flags, @@ -258,13 +297,14 @@ impl ConsensusDecoding for OutputFeatures { mint_non_fungible, sidechain_checkpoint, metadata: metadata.into(), + committee_checkpoint, }) } } impl Default for OutputFeatures { fn default() -> Self { - OutputFeatures::new_current_version(OutputFlags::empty(), 0, vec![], None, None, None, None, None) + OutputFeatures::new_current_version(OutputFlags::empty(), 0, vec![], None, None, None, None, None, None) } } @@ -324,6 +364,10 @@ mod test { merkle_root: [1u8; 32], committee: iter::repeat_with(PublicKey::default).take(50).collect(), }), + committee_checkpoint: Some(CommitteeCheckpointFeatures { + committee: iter::repeat_with(PublicKey::default).take(50).collect(), + effective_sidechain_height: u64::MAX, + }), } } @@ -340,6 +384,7 @@ mod test { subject.asset = None; subject.mint_non_fungible = None; subject.sidechain_checkpoint = None; + subject.committee_checkpoint = None; check_consensus_encoding_correctness(subject).unwrap(); } diff --git a/base_layer/core/src/transactions/transaction_components/output_features_version.rs b/base_layer/core/src/transactions/transaction_components/output_features_version.rs index 7f0c602388..a937d17a77 100644 --- a/base_layer/core/src/transactions/transaction_components/output_features_version.rs +++ b/base_layer/core/src/transactions/transaction_components/output_features_version.rs @@ -12,11 +12,12 @@ use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSi #[repr(u8)] pub enum OutputFeaturesVersion { V0 = 0, + V1 = 1, } impl OutputFeaturesVersion { pub fn get_current_version() -> Self { - Self::V0 + Self::V1 } pub fn as_u8(self) -> u8 { @@ -30,7 +31,8 @@ impl TryFrom for OutputFeaturesVersion { fn try_from(value: u8) -> Result { match value { 0 => Ok(OutputFeaturesVersion::V0), - _ => Err("Unknown version!".to_string()), + 1 => Ok(OutputFeaturesVersion::V1), + _ => Err("Unknown or unsupported OutputFeaturesVersion".into()), } } } diff --git a/base_layer/core/src/transactions/transaction_components/output_flags.rs b/base_layer/core/src/transactions/transaction_components/output_flags.rs index 00a5bfe60a..60e203b842 100644 --- a/base_layer/core/src/transactions/transaction_components/output_flags.rs +++ b/base_layer/core/src/transactions/transaction_components/output_flags.rs @@ -33,12 +33,13 @@ bitflags! { #[derive(Deserialize, Serialize)] pub struct OutputFlags: u8 { /// Output is a coinbase output, must not be spent until maturity - const COINBASE_OUTPUT = 0b0000_0001; - const NON_FUNGIBLE = 0b0000_1000; - const ASSET_REGISTRATION = 0b0000_0010 | Self::NON_FUNGIBLE.bits; - const MINT_NON_FUNGIBLE = 0b0000_0100 | Self::NON_FUNGIBLE.bits; - const BURN_NON_FUNGIBLE = 0b1000_0000 | Self::NON_FUNGIBLE.bits; + const COINBASE_OUTPUT = 0b0000_0001; + const NON_FUNGIBLE = 0b0000_1000; + const ASSET_REGISTRATION = 0b0000_0010 | Self::NON_FUNGIBLE.bits; + const MINT_NON_FUNGIBLE = 0b0000_0100 | Self::NON_FUNGIBLE.bits; + const BURN_NON_FUNGIBLE = 0b1000_0000 | Self::NON_FUNGIBLE.bits; const SIDECHAIN_CHECKPOINT = 0b0001_0000 | Self::NON_FUNGIBLE.bits; + const COMMITTEE_CHECKPOINT = 0b0010_0000 | Self::NON_FUNGIBLE.bits; } } diff --git a/base_layer/core/src/transactions/transaction_components/transaction_input.rs b/base_layer/core/src/transactions/transaction_components/transaction_input.rs index 32ff1858c9..a51d25fc48 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_input.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_input.rs @@ -106,7 +106,6 @@ impl TransactionInput { } /// Create a new Transaction Input with just a reference hash of the spent output - #[allow(clippy::too_many_arguments)] pub fn new_with_output_data( version: TransactionInputVersion, features: OutputFeatures, diff --git a/base_layer/core/src/transactions/transaction_components/transaction_output.rs b/base_layer/core/src/transactions/transaction_components/transaction_output.rs index ba05a9c8d0..20b8d7f0eb 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_output.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_output.rs @@ -97,7 +97,7 @@ pub struct TransactionOutput { /// An output for a transaction, includes a range proof and Tari script metadata impl TransactionOutput { /// Create new Transaction Output - #[allow(clippy::too_many_arguments)] + pub fn new( version: TransactionOutputVersion, features: OutputFeatures, @@ -260,7 +260,7 @@ impl TransactionOutput { } // Create commitment signature for the metadata - #[allow(clippy::too_many_arguments)] + fn create_metadata_signature( value: &MicroTari, spending_key: &BlindingFactor, diff --git a/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs b/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs index 862fad8385..4a8bc1ba2b 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs @@ -37,6 +37,7 @@ use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSi #[repr(u8)] pub enum TransactionOutputVersion { V0 = 0, + V1 = 1, } impl TransactionOutputVersion { @@ -55,6 +56,7 @@ impl TryFrom for TransactionOutputVersion { fn try_from(value: u8) -> Result { match value { 0 => Ok(TransactionOutputVersion::V0), + 1 => Ok(TransactionOutputVersion::V1), _ => Err("Unknown version!".to_string()), } } diff --git a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs index 00d8f7f11c..49beb99757 100644 --- a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs +++ b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs @@ -79,7 +79,7 @@ pub struct UnblindedOutput { impl UnblindedOutput { /// Creates a new un-blinded output - #[allow(clippy::too_many_arguments)] + pub fn new( version: TransactionOutputVersion, value: MicroTari, @@ -108,7 +108,6 @@ impl UnblindedOutput { } } - #[allow(clippy::too_many_arguments)] pub fn new_current_version( value: MicroTari, spending_key: BlindingFactor, diff --git a/base_layer/core/src/validation/helpers.rs b/base_layer/core/src/validation/helpers.rs index 98f040fa2e..fbefea2499 100644 --- a/base_layer/core/src/validation/helpers.rs +++ b/base_layer/core/src/validation/helpers.rs @@ -586,7 +586,8 @@ pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(), if header.kernel_mr != mmr_roots.kernel_mr { warn!( target: LOG_TARGET, - "Block header kernel MMR roots in {} do not match calculated roots. Expected: {}, Actual:{}", + "Block header kernel MMR roots in #{} {} do not match calculated roots. Expected: {}, Actual:{}", + header.height, header.hash().to_hex(), header.kernel_mr.to_hex(), mmr_roots.kernel_mr.to_hex() @@ -598,7 +599,8 @@ pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(), if header.kernel_mmr_size != mmr_roots.kernel_mmr_size { warn!( target: LOG_TARGET, - "Block header kernel MMR size in {} does not match. Expected: {}, Actual:{}", + "Block header kernel MMR size in #{} {} does not match. Expected: {}, Actual:{}", + header.height, header.hash().to_hex(), header.kernel_mmr_size, mmr_roots.kernel_mmr_size @@ -612,7 +614,8 @@ pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(), if header.output_mr != mmr_roots.output_mr { warn!( target: LOG_TARGET, - "Block header output MMR roots in {} do not match calculated roots. Expected: {}, Actual:{}", + "Block header output MMR roots in #{} {} do not match calculated roots. Expected: {}, Actual:{}", + header.height, header.hash().to_hex(), header.output_mr.to_hex(), mmr_roots.output_mr.to_hex() @@ -634,7 +637,7 @@ pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(), if header.output_mmr_size != mmr_roots.output_mmr_size { warn!( target: LOG_TARGET, - "Block header output MMR size in {} does not match. Expected: {}, Actual:{}", + "Block header output MMR size in {} does not match. Expected: {}, Actual: {}", header.hash().to_hex(), header.output_mmr_size, mmr_roots.output_mmr_size diff --git a/base_layer/core/tests/helpers/nodes.rs b/base_layer/core/tests/helpers/nodes.rs index bebd51aecc..df95d6cab4 100644 --- a/base_layer/core/tests/helpers/nodes.rs +++ b/base_layer/core/tests/helpers/nodes.rs @@ -393,7 +393,7 @@ async fn setup_comms_services( } // Helper function for starting the services of the Base node. -#[allow(clippy::too_many_arguments)] + async fn setup_base_node_services( node_identity: Arc, peers: Vec>, diff --git a/base_layer/p2p/src/services/liveness/service.rs b/base_layer/p2p/src/services/liveness/service.rs index c200e6e93c..3c16586d74 100644 --- a/base_layer/p2p/src/services/liveness/service.rs +++ b/base_layer/p2p/src/services/liveness/service.rs @@ -70,7 +70,6 @@ where TPingStream: Stream>, TRequestStream: Stream>>, { - #[allow(clippy::too_many_arguments)] pub fn new( config: LivenessConfig, request_rx: TRequestStream, diff --git a/base_layer/wallet/src/assets/asset_manager.rs b/base_layer/wallet/src/assets/asset_manager.rs index 57b5910e19..90b8bb482e 100644 --- a/base_layer/wallet/src/assets/asset_manager.rs +++ b/base_layer/wallet/src/assets/asset_manager.rs @@ -242,6 +242,34 @@ impl AssetManager { .await?; Ok((tx_id, transaction)) } + + pub async fn create_committee_checkpoint( + &mut self, + asset_public_key: PublicKey, + committee_pub_keys: Vec, + effective_sidechain_height: u64, + ) -> Result<(TxId, Transaction), WalletError> { + let output = self + .output_manager + .create_output_with_features( + 0.into(), + OutputFeatures::for_committee( + asset_public_key, + vec![2u8; 32], + committee_pub_keys.clone(), + effective_sidechain_height, + true, + ), + ) + .await?; + + let (tx_id, transaction) = self + .output_manager + .create_send_to_self_with_output(vec![output], 100.into(), None, None) + .await?; + + Ok((tx_id, transaction)) + } } fn convert_to_asset(unblinded_output: DbUnblindedOutput) -> Result { diff --git a/base_layer/wallet/src/assets/asset_manager_handle.rs b/base_layer/wallet/src/assets/asset_manager_handle.rs index c59cbac178..32dab1df1b 100644 --- a/base_layer/wallet/src/assets/asset_manager_handle.rs +++ b/base_layer/wallet/src/assets/asset_manager_handle.rs @@ -73,16 +73,15 @@ impl AssetManagerHandle { pub async fn create_initial_asset_checkpoint( &mut self, - public_key: &PublicKey, + asset_public_key: &PublicKey, merkle_root: FixedHash, - committee_public_keys: &[PublicKey], ) -> Result<(TxId, Transaction), WalletError> { match self .handle .call(AssetManagerRequest::CreateInitialCheckpoint { - asset_public_key: Box::new(public_key.clone()), + asset_public_key: Box::new(asset_public_key.clone()), merkle_root, - committee_public_keys: committee_public_keys.to_vec(), + committee_public_keys: Vec::new(), }) .await?? { @@ -99,7 +98,6 @@ impl AssetManagerHandle { public_key: &PublicKey, unique_id: &[u8], merkle_root: FixedHash, - committee_public_keys: &[PublicKey], ) -> Result<(TxId, Transaction), WalletError> { match self .handle @@ -107,7 +105,7 @@ impl AssetManagerHandle { asset_public_key: Box::new(public_key.clone()), merkle_root, unique_id: unique_id.to_vec(), - committee_public_keys: committee_public_keys.to_vec(), + committee_public_keys: Vec::new(), }) .await?? { @@ -119,6 +117,29 @@ impl AssetManagerHandle { } } + pub async fn create_committee_checkpoint( + &mut self, + public_key: &PublicKey, + committee_public_keys: &[PublicKey], + effective_sidechain_height: u64, + ) -> Result<(TxId, Transaction), WalletError> { + match self + .handle + .call(AssetManagerRequest::CreateCommitteeCheckpoint { + asset_public_key: Box::new(public_key.clone()), + committee_public_keys: committee_public_keys.to_vec(), + effective_sidechain_height, + }) + .await?? + { + AssetManagerResponse::CreateCommitteeCheckpoint { transaction, tx_id } => Ok((tx_id, *transaction)), + _ => Err(WalletError::UnexpectedApiResponse { + method: "create_committee_checkpoint".to_string(), + api: "AssetManagerService".to_string(), + }), + } + } + pub async fn create_registration_transaction( &mut self, name: String, diff --git a/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs b/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs index a88d1cce89..e9a8a600f1 100644 --- a/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs +++ b/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs @@ -159,6 +159,20 @@ impl AssetManagerService { tx_id, }) }, + AssetManagerRequest::CreateCommitteeCheckpoint { + asset_public_key, + committee_public_keys, + effective_sidechain_height, + } => { + let (tx_id, transaction) = self + .manager + .create_committee_checkpoint(*asset_public_key, committee_public_keys, effective_sidechain_height) + .await?; + Ok(AssetManagerResponse::CreateCommitteeCheckpoint { + transaction: Box::new(transaction), + tx_id, + }) + }, } } } diff --git a/base_layer/wallet/src/assets/infrastructure/mod.rs b/base_layer/wallet/src/assets/infrastructure/mod.rs index 1ef017db39..8cc7fcaf3f 100644 --- a/base_layer/wallet/src/assets/infrastructure/mod.rs +++ b/base_layer/wallet/src/assets/infrastructure/mod.rs @@ -62,6 +62,11 @@ pub enum AssetManagerRequest { merkle_root: FixedHash, committee_public_keys: Vec, }, + CreateCommitteeCheckpoint { + asset_public_key: Box, + committee_public_keys: Vec, + effective_sidechain_height: u64, + }, } pub enum AssetManagerResponse { @@ -71,4 +76,5 @@ pub enum AssetManagerResponse { CreateMintingTransaction { transaction: Box, tx_id: TxId }, CreateInitialCheckpoint { transaction: Box, tx_id: TxId }, CreateFollowOnCheckpoint { transaction: Box, tx_id: TxId }, + CreateCommitteeCheckpoint { transaction: Box, tx_id: TxId }, } diff --git a/base_layer/wallet/src/config.rs b/base_layer/wallet/src/config.rs index 2dc56f7d1d..1d2e00375c 100644 --- a/base_layer/wallet/src/config.rs +++ b/base_layer/wallet/src/config.rs @@ -48,7 +48,6 @@ pub struct WalletConfig { } impl WalletConfig { - #[allow(clippy::too_many_arguments)] pub fn new( comms_config: P2pConfig, factories: CryptoFactories, diff --git a/base_layer/wallet/src/output_manager_service/service.rs b/base_layer/wallet/src/output_manager_service/service.rs index 828fefeebb..6e0a10b73b 100644 --- a/base_layer/wallet/src/output_manager_service/service.rs +++ b/base_layer/wallet/src/output_manager_service/service.rs @@ -105,7 +105,6 @@ where TBackend: OutputManagerBackend + 'static, TWalletConnectivity: WalletConnectivityInterface, { - #[allow(clippy::too_many_arguments)] pub async fn new( config: OutputManagerServiceConfig, request_stream: reply_channel::Receiver< diff --git a/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs b/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs index 59819d5d85..f69754943d 100644 --- a/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs +++ b/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs @@ -100,7 +100,6 @@ pub struct TransactionSendProtocol { height: Option, } -#[allow(clippy::too_many_arguments)] impl TransactionSendProtocol where TBackend: TransactionBackend + 'static, diff --git a/base_layer/wallet/src/transaction_service/service.rs b/base_layer/wallet/src/transaction_service/service.rs index 3793454b73..b978c1e8f1 100644 --- a/base_layer/wallet/src/transaction_service/service.rs +++ b/base_layer/wallet/src/transaction_service/service.rs @@ -157,7 +157,6 @@ pub struct TransactionService< last_seen_tip_height: Option, } -#[allow(clippy::too_many_arguments)] impl< TTxStream, TTxReplyStream, diff --git a/base_layer/wallet/src/transaction_service/storage/models.rs b/base_layer/wallet/src/transaction_service/storage/models.rs index 62febbe9b0..81b06488ae 100644 --- a/base_layer/wallet/src/transaction_service/storage/models.rs +++ b/base_layer/wallet/src/transaction_service/storage/models.rs @@ -93,7 +93,6 @@ pub struct OutboundTransaction { } impl OutboundTransaction { - #[allow(clippy::too_many_arguments)] pub fn new( tx_id: TxId, destination_public_key: CommsPublicKey, @@ -146,7 +145,6 @@ pub struct CompletedTransaction { } impl CompletedTransaction { - #[allow(clippy::too_many_arguments)] pub fn new( tx_id: TxId, source_public_key: CommsPublicKey, diff --git a/base_layer/wallet/src/utxo_scanner_service/service.rs b/base_layer/wallet/src/utxo_scanner_service/service.rs index 0f20d76fc7..e382496c37 100644 --- a/base_layer/wallet/src/utxo_scanner_service/service.rs +++ b/base_layer/wallet/src/utxo_scanner_service/service.rs @@ -70,7 +70,6 @@ where TBackend: WalletBackend + 'static impl UtxoScannerService where TBackend: WalletBackend + 'static { - #[allow(clippy::too_many_arguments)] pub fn new( peer_seeds: Vec, retry_limit: usize, diff --git a/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs b/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs index 271ab0a3bc..bdc47604eb 100644 --- a/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs +++ b/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs @@ -108,7 +108,6 @@ impl UtxoScannerServiceBuilder { ) } - #[allow(clippy::too_many_arguments)] pub fn build_with_resources( &mut self, db: WalletDatabase, diff --git a/base_layer/wallet/src/wallet.rs b/base_layer/wallet/src/wallet.rs index 446e4e4cb5..1820b1e801 100644 --- a/base_layer/wallet/src/wallet.rs +++ b/base_layer/wallet/src/wallet.rs @@ -370,7 +370,7 @@ where /// Import an external spendable UTXO into the wallet. The output will be added to the Output Manager and made /// EncumberedToBeReceived. A faux incoming transaction will be created to provide a record of the event. The TxId /// of the generated transaction is returned. - #[allow(clippy::too_many_arguments)] + pub async fn import_utxo( &mut self, amount: MicroTari, diff --git a/base_layer/wallet/tests/transaction_service_tests/service.rs b/base_layer/wallet/tests/transaction_service_tests/service.rs index 45f7add1ba..888b607b5d 100644 --- a/base_layer/wallet/tests/transaction_service_tests/service.rs +++ b/base_layer/wallet/tests/transaction_service_tests/service.rs @@ -168,7 +168,6 @@ fn create_runtime() -> Runtime { .unwrap() } -#[allow(clippy::too_many_arguments)] pub fn setup_transaction_service>( runtime: &mut Runtime, node_identity: Arc, diff --git a/base_layer/wallet_ffi/src/callback_handler.rs b/base_layer/wallet_ffi/src/callback_handler.rs index 4cbaaa5232..248354c460 100644 --- a/base_layer/wallet_ffi/src/callback_handler.rs +++ b/base_layer/wallet_ffi/src/callback_handler.rs @@ -107,10 +107,10 @@ where TBackend: TransactionBackend + 'static connectivity_status_watch: watch::Receiver, } -#[allow(clippy::too_many_arguments)] impl CallbackHandler where TBackend: TransactionBackend + 'static { + #[allow(clippy::too_many_arguments)] pub fn new( db: TransactionDatabase, transaction_service_event_stream: TransactionEventReceiver, diff --git a/clippy.toml b/clippy.toml index 211b007c95..2da2a6362d 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1,2 @@ cognitive-complexity-threshold = 15 +too-many-arguments-threshold = 12 diff --git a/comms/dht/examples/memory_net/utilities.rs b/comms/dht/examples/memory_net/utilities.rs index 05e7d807ab..14787b5175 100644 --- a/comms/dht/examples/memory_net/utilities.rs +++ b/comms/dht/examples/memory_net/utilities.rs @@ -373,7 +373,6 @@ pub async fn do_network_wide_propagation(nodes: &mut [TestNode], origin_node_ind (num_successes, nodes.len() - 1) } -#[allow(clippy::too_many_arguments)] pub async fn do_store_and_forward_message_propagation( wallet: TestNode, wallets: &[TestNode], @@ -667,7 +666,6 @@ pub struct TestNode { pub shutdown: Shutdown, } -#[allow(clippy::too_many_arguments)] impl TestNode { pub fn new( comms: CommsNode, @@ -883,7 +881,6 @@ pub async fn make_node_from_node_identities( ) } -#[allow(clippy::too_many_arguments)] async fn setup_comms_dht( node_identity: Arc, storage: CommsDatabase, diff --git a/comms/dht/src/actor.rs b/comms/dht/src/actor.rs index 5dc0a61ada..b648d65f1a 100644 --- a/comms/dht/src/actor.rs +++ b/comms/dht/src/actor.rs @@ -214,7 +214,6 @@ pub struct DhtActor { } impl DhtActor { - #[allow(clippy::too_many_arguments)] pub fn new( config: Arc, conn: DbConnection, diff --git a/comms/dht/src/connectivity/mod.rs b/comms/dht/src/connectivity/mod.rs index 4afc7dab30..9b064d4082 100644 --- a/comms/dht/src/connectivity/mod.rs +++ b/comms/dht/src/connectivity/mod.rs @@ -87,7 +87,6 @@ pub struct DhtConnectivity { } impl DhtConnectivity { - #[allow(clippy::too_many_arguments)] pub fn new( config: Arc, peer_manager: Arc, diff --git a/comms/dht/src/outbound/broadcast.rs b/comms/dht/src/outbound/broadcast.rs index deab640263..5b47ca2934 100644 --- a/comms/dht/src/outbound/broadcast.rs +++ b/comms/dht/src/outbound/broadcast.rs @@ -400,7 +400,6 @@ where S: Service } } - #[allow(clippy::too_many_arguments)] async fn generate_send_messages( &mut self, selected_peers: Vec, @@ -484,7 +483,6 @@ where S: Service Ok(()) } - #[allow(clippy::too_many_arguments)] fn process_encryption( &self, encryption: &OutboundEncryption, diff --git a/comms/dht/src/store_forward/saf_handler/middleware.rs b/comms/dht/src/store_forward/saf_handler/middleware.rs index e2857e97e5..cd87e53610 100644 --- a/comms/dht/src/store_forward/saf_handler/middleware.rs +++ b/comms/dht/src/store_forward/saf_handler/middleware.rs @@ -51,7 +51,6 @@ pub struct MessageHandlerMiddleware { } impl MessageHandlerMiddleware { - #[allow(clippy::too_many_arguments)] pub fn new( config: SafConfig, next_service: S, diff --git a/comms/dht/src/store_forward/saf_handler/task.rs b/comms/dht/src/store_forward/saf_handler/task.rs index e852300b4c..e226d1c264 100644 --- a/comms/dht/src/store_forward/saf_handler/task.rs +++ b/comms/dht/src/store_forward/saf_handler/task.rs @@ -79,7 +79,6 @@ pub struct MessageHandlerTask { impl MessageHandlerTask where S: Service { - #[allow(clippy::too_many_arguments)] pub fn new( config: SafConfig, next_service: S, diff --git a/comms/dht/src/store_forward/service.rs b/comms/dht/src/store_forward/service.rs index d2c7af59cd..0e6596a567 100644 --- a/comms/dht/src/store_forward/service.rs +++ b/comms/dht/src/store_forward/service.rs @@ -191,7 +191,6 @@ pub struct StoreAndForwardService { } impl StoreAndForwardService { - #[allow(clippy::too_many_arguments)] pub fn new( config: SafConfig, conn: DbConnection, diff --git a/comms/dht/src/test_utils/makers.rs b/comms/dht/src/test_utils/makers.rs index 9d4a92ab13..fd72d315eb 100644 --- a/comms/dht/src/test_utils/makers.rs +++ b/comms/dht/src/test_utils/makers.rs @@ -70,7 +70,6 @@ pub fn make_comms_inbound_message(node_identity: &NodeIdentity, message: Bytes) InboundMessage::new(node_identity.node_id().clone(), message) } -#[allow(clippy::too_many_arguments)] pub fn make_dht_header( node_identity: &NodeIdentity, e_pk: &CommsPublicKey, diff --git a/comms/dht/tests/dht.rs b/comms/dht/tests/dht.rs index 441a4a8942..e05ae253f7 100644 --- a/comms/dht/tests/dht.rs +++ b/comms/dht/tests/dht.rs @@ -159,7 +159,6 @@ async fn make_node_with_node_identity>( } } -#[allow(clippy::too_many_arguments)] async fn setup_comms_dht( node_identity: Arc, storage: CommsDatabase, diff --git a/comms/src/connection_manager/dialer.rs b/comms/src/connection_manager/dialer.rs index 08b1bc9c45..35ed9a3c17 100644 --- a/comms/src/connection_manager/dialer.rs +++ b/comms/src/connection_manager/dialer.rs @@ -97,7 +97,6 @@ where TTransport::Output: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static, TBackoff: Backoff + Send + Sync + 'static, { - #[allow(clippy::too_many_arguments)] pub(crate) fn new( config: ConnectionManagerConfig, node_identity: Arc, @@ -361,7 +360,6 @@ where Ok(authenticated_public_key) } - #[allow(clippy::too_many_arguments)] #[tracing::instrument( level = "trace", skip(peer_manager, socket, conn_man_notifier, config, cancel_signal) diff --git a/comms/src/connection_manager/listener.rs b/comms/src/connection_manager/listener.rs index fb2221ed08..928f6a400b 100644 --- a/comms/src/connection_manager/listener.rs +++ b/comms/src/connection_manager/listener.rs @@ -90,7 +90,6 @@ where TTransport: Transport + Send + Sync + 'static, TTransport::Output: AsyncRead + AsyncWrite + Send + Unpin + 'static, { - #[allow(clippy::too_many_arguments)] pub fn new( config: ConnectionManagerConfig, bind_address: Multiaddr, @@ -334,7 +333,6 @@ where self.bounded_executor.spawn(inbound_fut).await; } - #[allow(clippy::too_many_arguments)] async fn perform_socket_upgrade_procedure( node_identity: Arc, peer_manager: Arc, diff --git a/comms/src/connection_manager/manager.rs b/comms/src/connection_manager/manager.rs index a61ae8c745..f3bb5cf31d 100644 --- a/comms/src/connection_manager/manager.rs +++ b/comms/src/connection_manager/manager.rs @@ -177,7 +177,6 @@ where TTransport::Output: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static, TBackoff: Backoff + Send + Sync + 'static, { - #[allow(clippy::too_many_arguments)] pub fn new( mut config: ConnectionManagerConfig, transport: TTransport, diff --git a/comms/src/connection_manager/peer_connection.rs b/comms/src/connection_manager/peer_connection.rs index 5151cc1395..330178bdc8 100644 --- a/comms/src/connection_manager/peer_connection.rs +++ b/comms/src/connection_manager/peer_connection.rs @@ -68,7 +68,6 @@ const LOG_TARGET: &str = "comms::connection_manager::peer_connection"; static ID_COUNTER: AtomicUsize = AtomicUsize::new(0); -#[allow(clippy::too_many_arguments)] pub fn create( connection: Yamux, peer_addr: Multiaddr, @@ -330,7 +329,6 @@ struct PeerConnectionActor { } impl PeerConnectionActor { - #[allow(clippy::too_many_arguments)] fn new( id: ConnectionId, peer_node_id: NodeId, diff --git a/comms/src/peer_manager/peer.rs b/comms/src/peer_manager/peer.rs index 4f871922f0..13f80ead1c 100644 --- a/comms/src/peer_manager/peer.rs +++ b/comms/src/peer_manager/peer.rs @@ -178,7 +178,7 @@ impl Peer { } #[allow(clippy::option_option)] - #[allow(clippy::too_many_arguments)] + pub fn update( &mut self, net_addresses: Option>, diff --git a/comms/src/peer_manager/peer_storage.rs b/comms/src/peer_manager/peer_storage.rs index 0f9ca71ac3..19daeb56a0 100644 --- a/comms/src/peer_manager/peer_storage.rs +++ b/comms/src/peer_manager/peer_storage.rs @@ -124,7 +124,7 @@ where DS: KeyValueStore /// Adds a peer to the routing table of the PeerManager if the peer does not already exist. When a peer already /// exist, the stored version will be replaced with the newly provided peer. - #[allow(clippy::too_many_arguments)] + #[allow(clippy::option_option)] pub fn update_peer( &mut self, diff --git a/comms/src/protocol/messaging/protocol.rs b/comms/src/protocol/messaging/protocol.rs index 6a391311fc..22b35abcf2 100644 --- a/comms/src/protocol/messaging/protocol.rs +++ b/comms/src/protocol/messaging/protocol.rs @@ -120,7 +120,6 @@ pub struct MessagingProtocol { } impl MessagingProtocol { - #[allow(clippy::too_many_arguments)] pub fn new( connectivity: ConnectivityRequester, proto_notification: mpsc::Receiver>, diff --git a/comms/src/protocol/rpc/client/mod.rs b/comms/src/protocol/rpc/client/mod.rs index cba5a9b1a1..18f55b53d1 100644 --- a/comms/src/protocol/rpc/client/mod.rs +++ b/comms/src/protocol/rpc/client/mod.rs @@ -408,7 +408,6 @@ struct RpcClientWorker { impl RpcClientWorker where TSubstream: AsyncRead + AsyncWrite + Unpin + Send + StreamId { - #[allow(clippy::too_many_arguments)] pub(self) fn new( config: RpcClientConfig, node_id: NodeId, diff --git a/comms/src/tor/hidden_service/controller.rs b/comms/src/tor/hidden_service/controller.rs index 83e37c3af7..c75909dc26 100644 --- a/comms/src/tor/hidden_service/controller.rs +++ b/comms/src/tor/hidden_service/controller.rs @@ -83,7 +83,6 @@ pub struct HiddenServiceController { } impl HiddenServiceController { - #[allow(clippy::too_many_arguments)] pub(super) fn new( control_server_addr: Multiaddr, control_server_auth: Authentication, diff --git a/dan_layer/core/src/workers/states/prepare.rs b/dan_layer/core/src/workers/states/prepare.rs index 4fc82dd2e3..8dc3d69833 100644 --- a/dan_layer/core/src/workers/states/prepare.rs +++ b/dan_layer/core/src/workers/states/prepare.rs @@ -120,7 +120,6 @@ where } } - #[allow(clippy::too_many_arguments)] pub async fn next_event< TChainStorageService: ChainStorageService, TUnitOfWork: ChainDbUnitOfWork, From fa80da923959b21fb8b59879a708036448ca2626 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 14 Feb 2022 13:31:23 +0200 Subject: [PATCH 2/9] fix test and add integration test --- .../src/automation/commands.rs | 11 +++++-- .../transaction_components/test.rs | 10 +++--- integration_tests/features/WalletCli.feature | 11 +++++++ .../features/support/wallet_cli_steps.js | 31 +++++++++++++++++-- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/applications/tari_console_wallet/src/automation/commands.rs b/applications/tari_console_wallet/src/automation/commands.rs index 37cf162ce5..2e4f3e1a58 100644 --- a/applications/tari_console_wallet/src/automation/commands.rs +++ b/applications/tari_console_wallet/src/automation/commands.rs @@ -798,19 +798,22 @@ pub async fn command_runner( tx_ids.push(tx_id); }, RegisterAsset => { - println!("Registering asset."); let name = parsed.args[0].to_string(); let message = format!("Register asset: {}", name); let mut manager = wallet.asset_manager.clone(); // todo: key manager #LOGGED let mut rng = rand::thread_rng(); let (_, public_key) = PublicKey::random_keypair(&mut rng); + let public_key_hex = public_key.to_hex(); + println!("Registering asset named: {name}"); + println!("with public key: {public_key_hex}"); let (tx_id, transaction) = manager .create_registration_transaction(name, public_key, vec![], None, None, vec![]) .await?; let _result = transaction_service .submit_transaction(tx_id, transaction, 0.into(), message) .await?; + println!("Done!"); }, MintTokens => { println!("Minting tokens for asset"); @@ -876,11 +879,13 @@ pub async fn command_runner( .await?; }, CreateCommitteeCheckpoint => { - println!("Creating Committee Checkpoint for Asset"); let asset_public_key = match parsed.args[0] { ParsedArgument::PublicKey(ref key) => Ok(key.clone()), _ => Err(CommandError::Argument), }?; + let public_key_hex = asset_public_key.to_hex(); + println!("Creating Committee Checkpoint for Asset"); + println!("with public key {public_key_hex}"); let committee_public_keys: Vec = parsed.args[1..] .iter() @@ -898,6 +903,7 @@ pub async fn command_runner( "Committee checkpoint with {} members for {}", num_members, asset_public_key ); + println!("with {num_members} committee members"); let mut asset_manager = wallet.asset_manager.clone(); // todo: effective sidechain height... @@ -908,6 +914,7 @@ pub async fn command_runner( let _result = transaction_service .submit_transaction(tx_id, transaction, 0.into(), message) .await?; + println!("Done!"); }, } } diff --git a/base_layer/core/src/transactions/transaction_components/test.rs b/base_layer/core/src/transactions/transaction_components/test.rs index 51828e0039..d4e0499c54 100644 --- a/base_layer/core/src/transactions/transaction_components/test.rs +++ b/base_layer/core/src/transactions/transaction_components/test.rs @@ -444,8 +444,8 @@ mod output_features { let features = OutputFeatures::with_maturity(0); let mut buf = Vec::new(); let written = features.consensus_encode(&mut buf).unwrap(); - assert_eq!(buf.len(), 9); - assert_eq!(written, 9); + assert_eq!(buf.len(), 10); + assert_eq!(written, 10); } #[test] @@ -453,10 +453,10 @@ mod output_features { let features = OutputFeatures::create_coinbase(u64::MAX); let known_size = features.consensus_encode_exact_size(); let mut buf = Vec::with_capacity(known_size); - assert_eq!(known_size, 18); + assert_eq!(known_size, 19); let written = features.consensus_encode(&mut buf).unwrap(); - assert_eq!(buf.len(), 18); - assert_eq!(written, 18); + assert_eq!(buf.len(), 19); + assert_eq!(written, 19); let decoded_features = OutputFeatures::consensus_decode(&mut &buf[..]).unwrap(); assert_eq!(features, decoded_features); } diff --git a/integration_tests/features/WalletCli.feature b/integration_tests/features/WalletCli.feature index 6ab1d20cdf..b9a287e7a3 100644 --- a/integration_tests/features/WalletCli.feature +++ b/integration_tests/features/WalletCli.feature @@ -136,3 +136,14 @@ Feature: Wallet CLI Given I have a base node BASE And I have wallet WALLET connected to base node BASE Then I run whois BASE on wallet WALLET via command line + + Scenario: As a user I want to set sidechain committee via command line + Given I have a base node BASE + And I have wallet WALLET connected to base node BASE + And I have mining node MINE connected to base node BASE and wallet WALLET + And mining node MINE mines 4 blocks + Then I wait for wallet WALLET to have at least 1000000 uT + And I register asset ONE on wallet WALLET via command line + And I create committee checkpoint for asset on wallet WALLET via command line + And mining node MINE mines 1 blocks + Then WALLET is connected to BASE \ No newline at end of file diff --git a/integration_tests/features/support/wallet_cli_steps.js b/integration_tests/features/support/wallet_cli_steps.js index 6efcae8520..d830144553 100644 --- a/integration_tests/features/support/wallet_cli_steps.js +++ b/integration_tests/features/support/wallet_cli_steps.js @@ -249,8 +249,35 @@ Then( wallet, `register-asset ${asset_name}` ); - // console.log(output.buffer); + console.log("output buffer:", output.buffer); expect(output.buffer).to.have.string("Registering asset"); + expect(output.buffer).to.have.string("with public key:"); + // hack out the public key + let split = output.buffer.split("with public key: "); + split = split[1].split("\n"); + this.asset_public_key = split[0]; + expect(this.asset_public_key.length).to.equal(64); + } +); + +Then( + "I create committee checkpoint for asset on wallet {word} via command line", + { timeout: 20 * 1000 }, + async function (wallet_name) { + // scenario needs "I register asset..." first to populate asset public key + expect(this.asset_public_key).to.exist; + const member = + "3ef702f33925dc65143f7bebcbe0c53902e8772a8fe7f5ddb703587c0203267d"; + let wallet = this.getWallet(wallet_name); + let output = await wallet_run_command( + wallet, + `create-committee-checkpoint ${this.asset_public_key} ${member}` + ); + // console.log(output.buffer); + expect(output.buffer).to.have.string(" committee members"); + let regex = /with \d+ committee members/; + let match = output.buffer.match(regex); + expect(match[0]).to.equal("with 1 committee members"); } ); @@ -266,7 +293,7 @@ Then( wallet, `mint-tokens ${byteArrayToHex(asset.public_key)} ${token_names}` ); - console.log(output.buffer); + // console.log(output.buffer); expect(output.buffer).to.have.string("Minting tokens for asset"); } ); From 03b2f264f1e7c9fb0b6a19dac085ac4c29c78054 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 14 Feb 2022 14:47:18 +0200 Subject: [PATCH 3/9] move committee call in collectibles out of asset checkpoint call --- .../src-tauri/src/commands/assets/mod.rs | 14 ++++++++++++-- .../tari_collectibles/src-tauri/src/main.rs | 1 + .../tari_collectibles/web-app/src/Create.js | 17 ++++++++++------- .../tari_collectibles/web-app/src/binding.js | 12 +++++++++++- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs b/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs index 3c0f8ea258..53b5c6b3b8 100644 --- a/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs +++ b/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs @@ -238,7 +238,6 @@ pub(crate) async fn assets_list_registered_assets( #[tauri::command] pub(crate) async fn assets_create_initial_checkpoint( asset_public_key: String, - committee: Vec, state: tauri::State<'_, ConcurrentAppState>, ) -> Result<(), Status> { let mmr = MerkleMountainRange::::new(MemBackendVec::new()); @@ -255,7 +254,18 @@ pub(crate) async fn assets_create_initial_checkpoint( .create_initial_asset_checkpoint(&asset_public_key, merkle_root) .await?; - // create committee checkpoint + Ok(()) +} + +#[tauri::command] +pub(crate) async fn assets_create_committee_checkpoint( + asset_public_key: String, + committee: Vec, + state: tauri::State<'_, ConcurrentAppState>, +) -> Result<(), Status> { + let mut client = state.create_wallet_client().await; + client.connect().await?; + // TODO: effective sidechain height... client .create_committee_checkpoint(&asset_public_key, committee, 0) diff --git a/applications/tari_collectibles/src-tauri/src/main.rs b/applications/tari_collectibles/src-tauri/src/main.rs index 0254de8b01..b9206cbe8e 100644 --- a/applications/tari_collectibles/src-tauri/src/main.rs +++ b/applications/tari_collectibles/src-tauri/src/main.rs @@ -41,6 +41,7 @@ fn main() -> Result<(), Box> { commands::assets::assets_list_owned, commands::assets::assets_list_registered_assets, commands::assets::assets_create_initial_checkpoint, + commands::assets::assets_create_committee_checkpoint, commands::assets::assets_get_registration, commands::asset_wallets::asset_wallets_create, commands::asset_wallets::asset_wallets_list, diff --git a/applications/tari_collectibles/web-app/src/Create.js b/applications/tari_collectibles/web-app/src/Create.js index 31ce44c95f..c079dd44f6 100644 --- a/applications/tari_collectibles/web-app/src/Create.js +++ b/applications/tari_collectibles/web-app/src/Create.js @@ -171,21 +171,24 @@ class Create extends React.Component { // TODO: How to create the initial checkpoint? if (this.state.tip003) { - let res = await binding.command_asset_create_initial_checkpoint( - publicKey, - this.state.tip003Data.committee - ); - - console.log(res); + let asset_registration = + await binding.command_asset_create_initial_checkpoint(publicKey); + console.log(asset_registration); + let committee_checkpoint = + await binding.command_asset_create_committee_checkpoint( + publicKey, + this.state.tip003Data.committee + ); + console.log(committee_checkpoint); } let history = this.props.history; history.push(`/assets/manage/${publicKey}`); } catch (err) { + console.error(err); this.setState({ error: "Could not create asset: " + err.message, }); - console.log(err); } this.setState({ isSaving: false }); }; diff --git a/applications/tari_collectibles/web-app/src/binding.js b/applications/tari_collectibles/web-app/src/binding.js index b774099e8a..0d119efb37 100644 --- a/applications/tari_collectibles/web-app/src/binding.js +++ b/applications/tari_collectibles/web-app/src/binding.js @@ -51,9 +51,18 @@ async function command_assets_get_registration(assetPubKey) { return await invoke("assets_get_registration", { assetPubKey }); } -async function command_asset_create_initial_checkpoint(assetPubKey, committee) { +async function command_asset_create_initial_checkpoint(assetPubKey) { return await invoke("assets_create_initial_checkpoint", { assetPubKey, + }); +} + +async function command_asset_create_committee_checkpoint( + assetPubKey, + committee +) { + return await invoke("assets_create_committee_checkpoint", { + assetPubKey, committee, }); } @@ -148,6 +157,7 @@ const commands = { command_assets_list_owned, command_assets_list_registered_assets, command_asset_create_initial_checkpoint, + command_asset_create_committee_checkpoint, command_next_asset_public_key, command_asset_wallets_create, command_asset_wallets_get_balance, From fcb7f1736d40192d236fb96d811369c3256247a8 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 15 Feb 2022 13:51:40 +0200 Subject: [PATCH 4/9] review comments 1 --- .../src-tauri/src/clients/wallet_client.rs | 12 ++++++------ base_layer/core/tests/helpers/nodes.rs | 1 - base_layer/wallet/src/assets/asset_manager.rs | 11 ++++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs b/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs index 32e1a1894e..ad66a02776 100644 --- a/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs +++ b/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs @@ -55,7 +55,7 @@ impl WalletClient { Ok(()) } - fn get_inner( + fn get_inner_mut( &mut self, ) -> Result<&mut grpc::wallet_client::WalletClient, CollectiblesError> { @@ -73,7 +73,7 @@ impl WalletClient { template_ids_implemented: Vec, template_parameters: Vec, ) -> Result { - let inner = self.get_inner()?; + let inner = self.get_inner_mut()?; let request = RegisterAssetRequest { name, public_key: public_key.as_bytes().into(), @@ -97,7 +97,7 @@ impl WalletClient { pub async fn list_owned_assets( &mut self, ) -> Result { - let inner = self.get_inner()?; + let inner = self.get_inner_mut()?; let request = grpc::Empty {}; let result = inner @@ -116,7 +116,7 @@ impl WalletClient { asset_public_key: &str, merkle_root: Vec, ) -> Result { - let inner = self.get_inner()?; + let inner = self.get_inner_mut()?; let committee = vec![]; let request = grpc::CreateInitialAssetCheckpointRequest { asset_public_key: Vec::from_hex(asset_public_key)?, @@ -140,7 +140,7 @@ impl WalletClient { committee: Vec, effective_sidechain_height: u64, ) -> Result { - let inner = self.get_inner()?; + let inner = self.get_inner_mut()?; let committee = committee .iter() .map(|s| Vec::from_hex(s)) @@ -165,7 +165,7 @@ impl WalletClient { pub async fn get_unspent_amounts( &mut self, ) -> Result { - let inner = self.get_inner()?; + let inner = self.get_inner_mut()?; let request = grpc::Empty {}; let result = inner.get_unspent_amounts(request).await.map_err(|source| { CollectiblesError::ClientRequest { diff --git a/base_layer/core/tests/helpers/nodes.rs b/base_layer/core/tests/helpers/nodes.rs index df95d6cab4..35d4daf584 100644 --- a/base_layer/core/tests/helpers/nodes.rs +++ b/base_layer/core/tests/helpers/nodes.rs @@ -393,7 +393,6 @@ async fn setup_comms_services( } // Helper function for starting the services of the Base node. - async fn setup_base_node_services( node_identity: Arc, peers: Vec>, diff --git a/base_layer/wallet/src/assets/asset_manager.rs b/base_layer/wallet/src/assets/asset_manager.rs index 90b8bb482e..7f9e486e11 100644 --- a/base_layer/wallet/src/assets/asset_manager.rs +++ b/base_layer/wallet/src/assets/asset_manager.rs @@ -40,6 +40,7 @@ use crate::{ }; const LOG_TARGET: &str = "wallet::assets::asset_manager"; +const ASSET_FPG: u64 = 10; pub(crate) struct AssetManager { output_database: OutputManagerDatabase, @@ -112,7 +113,7 @@ impl AssetManager { debug!(target: LOG_TARGET, "Created output: {:?}", output); let (tx_id, transaction) = self .output_manager - .create_send_to_self_with_output(vec![output], 20.into(), None, None) + .create_send_to_self_with_output(vec![output], ASSET_FPG.into(), None, None) .await?; Ok((tx_id, transaction)) } @@ -143,7 +144,7 @@ impl AssetManager { let (tx_id, transaction) = self .output_manager - .create_send_to_self_with_output(outputs, 100.into(), None, None) + .create_send_to_self_with_output(outputs, ASSET_FPG.into(), None, None) .await?; Ok((tx_id, transaction)) } @@ -190,7 +191,7 @@ impl AssetManager { // ))); let (tx_id, transaction) = self .output_manager - .create_send_to_self_with_output(vec![output], 100.into(), None, None) + .create_send_to_self_with_output(vec![output], ASSET_FPG.into(), None, None) .await?; Ok((tx_id, transaction)) } @@ -238,7 +239,7 @@ impl AssetManager { // ))); let (tx_id, transaction) = self .output_manager - .create_send_to_self_with_output(vec![output], 100.into(), Some(unique_id), Some(asset_pub_key)) + .create_send_to_self_with_output(vec![output], ASSET_FPG.into(), Some(unique_id), Some(asset_pub_key)) .await?; Ok((tx_id, transaction)) } @@ -265,7 +266,7 @@ impl AssetManager { let (tx_id, transaction) = self .output_manager - .create_send_to_self_with_output(vec![output], 100.into(), None, None) + .create_send_to_self_with_output(vec![output], ASSET_FPG.into(), None, None) .await?; Ok((tx_id, transaction)) From c91c7ceeaa9cf247e55124ce4823daf33689b490 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 15 Feb 2022 14:44:12 +0200 Subject: [PATCH 5/9] rename to committee definition --- .gitignore | 6 ++-- applications/tari_app_grpc/proto/types.proto | 4 +-- applications/tari_app_grpc/proto/wallet.proto | 6 ++-- .../src/conversions/output_features.rs | 14 ++++----- .../src-tauri/src/clients/wallet_client.rs | 10 +++---- .../src-tauri/src/commands/assets/mod.rs | 4 +-- .../tari_collectibles/src-tauri/src/main.rs | 2 +- .../tari_collectibles/web-app/src/Create.js | 6 ++-- .../tari_collectibles/web-app/src/binding.js | 6 ++-- .../src/automation/command_parser.rs | 4 +-- .../src/automation/commands.rs | 6 ++-- .../src/grpc/wallet_grpc_server.rs | 14 ++++----- base_layer/core/src/blocks/genesis_block.rs | 2 +- base_layer/core/src/proto/transaction.proto | 6 ++-- base_layer/core/src/proto/transaction.rs | 14 ++++----- ...es.rs => committee_definition_features.rs} | 12 ++++---- .../transaction_components/mod.rs | 4 +-- .../transaction_components/output_features.rs | 30 +++++++++---------- .../transaction_components/output_flags.rs | 2 +- base_layer/wallet/src/assets/asset_manager.rs | 2 +- .../wallet/src/assets/asset_manager_handle.rs | 4 +-- .../infrastructure/asset_manager_service.rs | 2 +- .../features/support/wallet_cli_steps.js | 2 +- 23 files changed, 82 insertions(+), 80 deletions(-) rename base_layer/core/src/transactions/transaction_components/{committee_checkpoint_features.rs => committee_definition_features.rs} (91%) diff --git a/.gitignore b/.gitignore index f0a7c73bd7..41c569e532 100644 --- a/.gitignore +++ b/.gitignore @@ -46,5 +46,7 @@ node_modules buildtools/Output/ /applications/tari_collectibles/src-tauri/data -# Asset files -assets/ +# some folders called assets are kind of important now +# any specific "assets" folders should be gitignored +# closer to where they live +#assets/ diff --git a/applications/tari_app_grpc/proto/types.proto b/applications/tari_app_grpc/proto/types.proto index f6f5b2ba61..727f53f292 100644 --- a/applications/tari_app_grpc/proto/types.proto +++ b/applications/tari_app_grpc/proto/types.proto @@ -225,7 +225,7 @@ message OutputFeatures { SideChainCheckpointFeatures sidechain_checkpoint = 8; // Version uint32 version = 9; - CommitteeCheckpointFeatures committee_checkpoint = 10; + CommitteeDefinitionFeatures committee_definition = 10; } message AssetOutputFeatures { @@ -250,7 +250,7 @@ message SideChainCheckpointFeatures { repeated bytes committee = 2; } -message CommitteeCheckpointFeatures { +message CommitteeDefinitionFeatures { repeated bytes committee = 1; uint64 effective_sidechain_height = 2; } diff --git a/applications/tari_app_grpc/proto/wallet.proto b/applications/tari_app_grpc/proto/wallet.proto index cfb4dd8c13..83ae93b08b 100644 --- a/applications/tari_app_grpc/proto/wallet.proto +++ b/applications/tari_app_grpc/proto/wallet.proto @@ -70,7 +70,7 @@ service Wallet { rpc CreateInitialAssetCheckpoint(CreateInitialAssetCheckpointRequest) returns (CreateInitialAssetCheckpointResponse); // TODO: Needs a better name pls rpc CreateFollowOnAssetCheckpoint(CreateFollowOnAssetCheckpointRequest) returns (CreateFollowOnAssetCheckpointResponse); - rpc CreateCommitteeCheckpoint(CreateCommitteeCheckpointRequest) returns (CreateCommitteeCheckpointResponse); + rpc CreateCommitteeDefinition(CreateCommitteeDefinitionRequest) returns (CreateCommitteeDefinitionResponse); rpc GetOwnedAssets(Empty) returns (GetOwnedAssetsResponse); @@ -281,13 +281,13 @@ message CreateFollowOnAssetCheckpointResponse { } -message CreateCommitteeCheckpointRequest { +message CreateCommitteeDefinitionRequest { bytes asset_public_key = 1; repeated bytes committee = 2; uint64 effective_sidechain_height = 3; } -message CreateCommitteeCheckpointResponse { +message CreateCommitteeDefinitionResponse { } diff --git a/applications/tari_app_grpc/src/conversions/output_features.rs b/applications/tari_app_grpc/src/conversions/output_features.rs index c9a1fb5899..33b62bde32 100644 --- a/applications/tari_app_grpc/src/conversions/output_features.rs +++ b/applications/tari_app_grpc/src/conversions/output_features.rs @@ -28,7 +28,7 @@ use tari_common_types::{ }; use tari_core::transactions::transaction_components::{ AssetOutputFeatures, - CommitteeCheckpointFeatures, + CommitteeDefinitionFeatures, MintNonFungibleFeatures, OutputFeatures, OutputFeaturesVersion, @@ -68,7 +68,7 @@ impl TryFrom for OutputFeatures { features.asset.map(|a| a.try_into()).transpose()?, features.mint_non_fungible.map(|m| m.try_into()).transpose()?, features.sidechain_checkpoint.map(|s| s.try_into()).transpose()?, - features.committee_checkpoint.map(|c| c.try_into()).transpose()?, + features.committee_definition.map(|c| c.try_into()).transpose()?, )) } } @@ -88,7 +88,7 @@ impl From for grpc::OutputFeatures { mint_non_fungible: features.mint_non_fungible.map(|m| m.into()), sidechain_checkpoint: features.sidechain_checkpoint.map(|m| m.into()), version: features.version as u32, - committee_checkpoint: features.committee_checkpoint.map(|c| c.into()), + committee_definition: features.committee_definition.map(|c| c.into()), } } } @@ -188,8 +188,8 @@ impl TryFrom for SideChainCheckpointFeatures } } -impl From for grpc::CommitteeCheckpointFeatures { - fn from(value: CommitteeCheckpointFeatures) -> Self { +impl From for grpc::CommitteeDefinitionFeatures { + fn from(value: CommitteeDefinitionFeatures) -> Self { Self { committee: value.committee.iter().map(|c| c.as_bytes().to_vec()).collect(), effective_sidechain_height: value.effective_sidechain_height, @@ -197,10 +197,10 @@ impl From for grpc::CommitteeCheckpointFeatures { } } -impl TryFrom for CommitteeCheckpointFeatures { +impl TryFrom for CommitteeDefinitionFeatures { type Error = String; - fn try_from(value: grpc::CommitteeCheckpointFeatures) -> Result { + fn try_from(value: grpc::CommitteeDefinitionFeatures) -> Result { let committee = value .committee .iter() diff --git a/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs b/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs index ad66a02776..d715a9b357 100644 --- a/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs +++ b/applications/tari_collectibles/src-tauri/src/clients/wallet_client.rs @@ -134,28 +134,28 @@ impl WalletClient { Ok(result.into_inner()) } - pub async fn create_committee_checkpoint( + pub async fn create_committee_definition( &mut self, asset_public_key: &str, committee: Vec, effective_sidechain_height: u64, - ) -> Result { + ) -> Result { let inner = self.get_inner_mut()?; let committee = committee .iter() .map(|s| Vec::from_hex(s)) .collect::, _>>()?; - let request = grpc::CreateCommitteeCheckpointRequest { + let request = grpc::CreateCommitteeDefinitionRequest { asset_public_key: Vec::from_hex(asset_public_key)?, committee, effective_sidechain_height, }; let result = inner - .create_committee_checkpoint(request) + .create_committee_definition(request) .await .map_err(|source| CollectiblesError::ClientRequest { - request: "create_committee_checkpoint".to_string(), + request: "create_committee_definition".to_string(), source, })?; debug!(target: LOG_TARGET, "result {:?}", result); diff --git a/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs b/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs index 53b5c6b3b8..c7c000e0e8 100644 --- a/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs +++ b/applications/tari_collectibles/src-tauri/src/commands/assets/mod.rs @@ -258,7 +258,7 @@ pub(crate) async fn assets_create_initial_checkpoint( } #[tauri::command] -pub(crate) async fn assets_create_committee_checkpoint( +pub(crate) async fn assets_create_committee_definition( asset_public_key: String, committee: Vec, state: tauri::State<'_, ConcurrentAppState>, @@ -268,7 +268,7 @@ pub(crate) async fn assets_create_committee_checkpoint( // TODO: effective sidechain height... client - .create_committee_checkpoint(&asset_public_key, committee, 0) + .create_committee_definition(&asset_public_key, committee, 0) .await?; Ok(()) diff --git a/applications/tari_collectibles/src-tauri/src/main.rs b/applications/tari_collectibles/src-tauri/src/main.rs index b9206cbe8e..1472d1ab1e 100644 --- a/applications/tari_collectibles/src-tauri/src/main.rs +++ b/applications/tari_collectibles/src-tauri/src/main.rs @@ -41,7 +41,7 @@ fn main() -> Result<(), Box> { commands::assets::assets_list_owned, commands::assets::assets_list_registered_assets, commands::assets::assets_create_initial_checkpoint, - commands::assets::assets_create_committee_checkpoint, + commands::assets::assets_create_committee_definition, commands::assets::assets_get_registration, commands::asset_wallets::asset_wallets_create, commands::asset_wallets::asset_wallets_list, diff --git a/applications/tari_collectibles/web-app/src/Create.js b/applications/tari_collectibles/web-app/src/Create.js index c079dd44f6..135bb380e8 100644 --- a/applications/tari_collectibles/web-app/src/Create.js +++ b/applications/tari_collectibles/web-app/src/Create.js @@ -174,12 +174,12 @@ class Create extends React.Component { let asset_registration = await binding.command_asset_create_initial_checkpoint(publicKey); console.log(asset_registration); - let committee_checkpoint = - await binding.command_asset_create_committee_checkpoint( + let committee_definition = + await binding.command_asset_create_committee_definition( publicKey, this.state.tip003Data.committee ); - console.log(committee_checkpoint); + console.log(committee_definition); } let history = this.props.history; diff --git a/applications/tari_collectibles/web-app/src/binding.js b/applications/tari_collectibles/web-app/src/binding.js index 0d119efb37..8828d15159 100644 --- a/applications/tari_collectibles/web-app/src/binding.js +++ b/applications/tari_collectibles/web-app/src/binding.js @@ -57,11 +57,11 @@ async function command_asset_create_initial_checkpoint(assetPubKey) { }); } -async function command_asset_create_committee_checkpoint( +async function command_asset_create_committee_definition( assetPubKey, committee ) { - return await invoke("assets_create_committee_checkpoint", { + return await invoke("assets_create_committee_definition", { assetPubKey, committee, }); @@ -157,7 +157,7 @@ const commands = { command_assets_list_owned, command_assets_list_registered_assets, command_asset_create_initial_checkpoint, - command_asset_create_committee_checkpoint, + command_asset_create_committee_definition, command_next_asset_public_key, command_asset_wallets_create, command_asset_wallets_get_balance, diff --git a/applications/tari_console_wallet/src/automation/command_parser.rs b/applications/tari_console_wallet/src/automation/command_parser.rs index 37ef95d44b..bb9c0ad2c1 100644 --- a/applications/tari_console_wallet/src/automation/command_parser.rs +++ b/applications/tari_console_wallet/src/automation/command_parser.rs @@ -65,7 +65,7 @@ impl Display for ParsedCommand { RegisterAsset => "register-asset", MintTokens => "mint-tokens", CreateInitialCheckpoint => "create-initial-checkpoint", - CreateCommitteeCheckpoint => "create-committee-checkpoint", + CreateCommitteeDefinition => "create-committee-definition", }; let args = self @@ -142,7 +142,7 @@ pub fn parse_command(command: &str) -> Result { // mint-tokens pub_key nft_id1 nft_id2 MintTokens => parser_builder(args).pub_key().text_array().build()?, CreateInitialCheckpoint => parser_builder(args).pub_key().text().build()?, - CreateCommitteeCheckpoint => parser_builder(args).pub_key().pub_key_array().build()?, + CreateCommitteeDefinition => parser_builder(args).pub_key().pub_key_array().build()?, }; Ok(ParsedCommand { command, args }) diff --git a/applications/tari_console_wallet/src/automation/commands.rs b/applications/tari_console_wallet/src/automation/commands.rs index 2e4f3e1a58..38d8c5615d 100644 --- a/applications/tari_console_wallet/src/automation/commands.rs +++ b/applications/tari_console_wallet/src/automation/commands.rs @@ -94,7 +94,7 @@ pub enum WalletCommand { RegisterAsset, MintTokens, CreateInitialCheckpoint, - CreateCommitteeCheckpoint, + CreateCommitteeDefinition, } #[derive(Debug, EnumString, PartialEq, Clone)] @@ -878,7 +878,7 @@ pub async fn command_runner( .submit_transaction(tx_id, transaction, 0.into(), message) .await?; }, - CreateCommitteeCheckpoint => { + CreateCommitteeDefinition => { let asset_public_key = match parsed.args[0] { ParsedArgument::PublicKey(ref key) => Ok(key.clone()), _ => Err(CommandError::Argument), @@ -908,7 +908,7 @@ pub async fn command_runner( let mut asset_manager = wallet.asset_manager.clone(); // todo: effective sidechain height... let (tx_id, transaction) = asset_manager - .create_committee_checkpoint(&asset_public_key, &committee_public_keys, 0) + .create_committee_definition(&asset_public_key, &committee_public_keys, 0) .await?; let _result = transaction_service diff --git a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs index 7ea076236a..4e58336267 100644 --- a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs +++ b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs @@ -36,8 +36,8 @@ use tari_app_grpc::{ ClaimShaAtomicSwapResponse, CoinSplitRequest, CoinSplitResponse, - CreateCommitteeCheckpointRequest, - CreateCommitteeCheckpointResponse, + CreateCommitteeDefinitionRequest, + CreateCommitteeDefinitionResponse, CreateFollowOnAssetCheckpointRequest, CreateFollowOnAssetCheckpointResponse, CreateInitialAssetCheckpointRequest, @@ -720,10 +720,10 @@ impl wallet_server::Wallet for WalletGrpcServer { Ok(Response::new(CreateFollowOnAssetCheckpointResponse {})) } - async fn create_committee_checkpoint( + async fn create_committee_definition( &self, - request: Request, - ) -> Result, Status> { + request: Request, + ) -> Result, Status> { let mut asset_manager = self.wallet.asset_manager.clone(); let mut transaction_service = self.wallet.transaction_service.clone(); let message = request.into_inner(); @@ -739,7 +739,7 @@ impl wallet_server::Wallet for WalletGrpcServer { let effective_sidechain_height = message.effective_sidechain_height; let (tx_id, transaction) = asset_manager - .create_committee_checkpoint(&asset_public_key, &committee_public_keys, effective_sidechain_height) + .create_committee_definition(&asset_public_key, &committee_public_keys, effective_sidechain_height) .await .map_err(|e| Status::internal(e.to_string()))?; @@ -752,7 +752,7 @@ impl wallet_server::Wallet for WalletGrpcServer { .await .map_err(|e| Status::internal(e.to_string()))?; - Ok(Response::new(CreateCommitteeCheckpointResponse {})) + Ok(Response::new(CreateCommitteeDefinitionResponse {})) } async fn mint_tokens(&self, request: Request) -> Result, Status> { diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 6a83d62659..c9ac1978d4 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -249,7 +249,7 @@ fn get_dibbler_genesis_block_raw() -> Block { asset: None, mint_non_fungible: None, sidechain_checkpoint: None, - committee_checkpoint: None + committee_definition: None }, Commitment::from_hex("e2b9ee8fdf05f9fa8fd7598d4568b539eef694e58cdae84c779140271a96d733 ").unwrap(), BulletRangeProof::from_hex("0c02c6d9bdbd1c21b29ee0f83bed597ed07f71a60f99ddcbc02550059c4c08020438f8fc25c69160dc6af81f84c037fc79b9f4a7baa93ab4d6ef1640356d9b575efe1f3f8b40f6c64d1a964aab215491f79738ccac1712d756607626442dda37ac30010dc663985153786cc53c865c01bfec186a803c1edb1a34efa3088ec221016a63cdbd2b58fa4c258bfbf0cff6b793ab62f5db0fb781f046effb5f4e7c0a956c2e042e3f0c16a72f20a624625fa6dc0b742e49e0158a50c8abde54834e04bb35baef0c258da30b738256549e3a2612ff89b4f6bfe82d16aa10b38daabe0df6b922717cb4b1604ab97a2a5efa4d325beb56c5419cff185d61e1a0fc9e374098bf4a10404d788141e2c77de222d68c14b421b62f300898c25487f491aff26be85e54c011e90cc96aff6b31993ce74233674fb150de929fbc259bcc7808a84432cf28bf83c2a0fbf2b47a6244fbafa02ca4f5c9d46c5380fe8eaed734f1d56e769e59800137900cb5905191bbb463cbcb4ea0a2073d716f18878ed4455d19426a2c1133bf703510bf0f1b3b70e9e5ee6fbb70a8e710fd0a4b8f37eacfdeef3df66e461f16ffdb270a7181505b1358f56578840bbfa284444c35160794f0294300ecb3fde701a3f5ed9234e4c196b93fd70633069eeb184ab53685b5324c963a7428094f0c7d4306b5da6ef5fb68d085c32adabe004bebcbf335ee8fc92e5e034edcb035872d08f139e9445539241ff9b9fbebbc0e7b248cbd97fa7c6f3d7823085893c9ced1685d69d2a7cf111f81e086927565c301d4e33639def1139bd5245a0ae9085d5ba10cdc1f89fc7a7fa95cc3aa11784ec40ebf57475ffb4f2b2042018e3dbe905ebd5d0ebe533f36f43f709110372c94258a59e53c9b319adca30c8e9f4f92d5937f994ff36a5bb38a15682187dc8734162f45e169a97a36fb5a05").unwrap(), diff --git a/base_layer/core/src/proto/transaction.proto b/base_layer/core/src/proto/transaction.proto index 813e47dd8c..c739837bd4 100644 --- a/base_layer/core/src/proto/transaction.proto +++ b/base_layer/core/src/proto/transaction.proto @@ -74,7 +74,7 @@ message TransactionOutput { uint32 version = 8; } -// Options for UTXO's +// Options for UTXOs message OutputFeatures { // Flags are the feature flags that differentiate between outputs, eg Coinbase all of which has different rules uint32 flags = 1; @@ -95,7 +95,7 @@ message OutputFeatures { SideChainCheckpointFeatures sidechain_checkpoint = 8; // Version uint32 version = 9; - CommitteeCheckpointFeatures committee_checkpoint = 10; + CommitteeDefinitionFeatures committee_definition = 10; } message AssetOutputFeatures { @@ -120,7 +120,7 @@ message SideChainCheckpointFeatures { repeated bytes committee = 2; } -message CommitteeCheckpointFeatures { +message CommitteeDefinitionFeatures { repeated bytes committee = 1; uint64 effective_sidechain_height = 2; } diff --git a/base_layer/core/src/proto/transaction.rs b/base_layer/core/src/proto/transaction.rs index 923ca70c94..89af456449 100644 --- a/base_layer/core/src/proto/transaction.rs +++ b/base_layer/core/src/proto/transaction.rs @@ -42,7 +42,7 @@ use crate::{ tari_amount::MicroTari, transaction_components::{ AssetOutputFeatures, - CommitteeCheckpointFeatures, + CommitteeDefinitionFeatures, KernelFeatures, MintNonFungibleFeatures, OutputFeatures, @@ -302,7 +302,7 @@ impl TryFrom for OutputFeatures { None => None, }, features.sidechain_checkpoint.map(|s| s.try_into()).transpose()?, - features.committee_checkpoint.map(|c| c.try_into()).transpose()?, + features.committee_definition.map(|c| c.try_into()).transpose()?, )) } } @@ -322,7 +322,7 @@ impl From for proto::types::OutputFeatures { mint_non_fungible: features.mint_non_fungible.map(|m| m.into()), sidechain_checkpoint: features.sidechain_checkpoint.map(|s| s.into()), version: features.version as u32, - committee_checkpoint: features.committee_checkpoint.map(|c| c.into()), + committee_definition: features.committee_definition.map(|c| c.into()), } } } @@ -429,10 +429,10 @@ impl From for proto::types::SideChainCheckpointFeat } } -impl TryFrom for CommitteeCheckpointFeatures { +impl TryFrom for CommitteeDefinitionFeatures { type Error = String; - fn try_from(value: proto::types::CommitteeCheckpointFeatures) -> Result { + fn try_from(value: proto::types::CommitteeDefinitionFeatures) -> Result { let committee = value .committee .into_iter() @@ -447,8 +447,8 @@ impl TryFrom for CommitteeCheckpointF } } -impl From for proto::types::CommitteeCheckpointFeatures { - fn from(value: CommitteeCheckpointFeatures) -> Self { +impl From for proto::types::CommitteeDefinitionFeatures { + fn from(value: CommitteeDefinitionFeatures) -> Self { Self { committee: value.committee.into_iter().map(|c| c.as_bytes().to_vec()).collect(), effective_sidechain_height: value.effective_sidechain_height, diff --git a/base_layer/core/src/transactions/transaction_components/committee_checkpoint_features.rs b/base_layer/core/src/transactions/transaction_components/committee_definition_features.rs similarity index 91% rename from base_layer/core/src/transactions/transaction_components/committee_checkpoint_features.rs rename to base_layer/core/src/transactions/transaction_components/committee_definition_features.rs index 3828dfa165..e0e6ae49a5 100644 --- a/base_layer/core/src/transactions/transaction_components/committee_checkpoint_features.rs +++ b/base_layer/core/src/transactions/transaction_components/committee_definition_features.rs @@ -30,12 +30,12 @@ use tari_crypto::keys::PublicKey as PublicKeyTrait; use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized, MaxSizeVec}; #[derive(Debug, Clone, Hash, PartialEq, Deserialize, Serialize, Eq)] -pub struct CommitteeCheckpointFeatures { +pub struct CommitteeDefinitionFeatures { pub committee: Vec, pub effective_sidechain_height: u64, } -impl ConsensusEncoding for CommitteeCheckpointFeatures { +impl ConsensusEncoding for CommitteeDefinitionFeatures { fn consensus_encode(&self, writer: &mut W) -> Result { let mut written = self.committee.consensus_encode(writer)?; written += self.effective_sidechain_height.consensus_encode(writer)?; @@ -43,7 +43,7 @@ impl ConsensusEncoding for CommitteeCheckpointFeatures { } } -impl ConsensusEncodingSized for CommitteeCheckpointFeatures { +impl ConsensusEncodingSized for CommitteeDefinitionFeatures { fn consensus_encode_exact_size(&self) -> usize { self.committee.len().required_space() + self.committee.len() * PublicKey::key_length() + @@ -51,7 +51,7 @@ impl ConsensusEncodingSized for CommitteeCheckpointFeatures { } } -impl ConsensusDecoding for CommitteeCheckpointFeatures { +impl ConsensusDecoding for CommitteeDefinitionFeatures { fn consensus_decode(reader: &mut R) -> Result { const MAX_COMMITTEE_KEYS: usize = 50; let committee = MaxSizeVec::::consensus_decode(reader)?; @@ -73,7 +73,7 @@ mod test { #[test] fn it_encodes_and_decodes_correctly() { - let subject = CommitteeCheckpointFeatures { + let subject = CommitteeDefinitionFeatures { committee: iter::repeat_with(PublicKey::default).take(50).collect(), effective_sidechain_height: 123, }; @@ -83,7 +83,7 @@ mod test { #[test] fn it_fails_for_too_many_committee_pks() { - let subject = CommitteeCheckpointFeatures { + let subject = CommitteeDefinitionFeatures { committee: iter::repeat_with(PublicKey::default).take(51).collect(), effective_sidechain_height: 321, }; diff --git a/base_layer/core/src/transactions/transaction_components/mod.rs b/base_layer/core/src/transactions/transaction_components/mod.rs index c9448e18b2..96764c448f 100644 --- a/base_layer/core/src/transactions/transaction_components/mod.rs +++ b/base_layer/core/src/transactions/transaction_components/mod.rs @@ -25,7 +25,7 @@ pub use asset_output_features::AssetOutputFeatures; use blake2::Digest; -pub use committee_checkpoint_features::CommitteeCheckpointFeatures; +pub use committee_definition_features::CommitteeDefinitionFeatures; pub use error::TransactionError; pub use full_rewind_result::FullRewindResult; pub use kernel_builder::KernelBuilder; @@ -52,7 +52,7 @@ pub use unblinded_output::UnblindedOutput; pub use unblinded_output_builder::UnblindedOutputBuilder; mod asset_output_features; -mod committee_checkpoint_features; +mod committee_definition_features; mod error; mod full_rewind_result; mod kernel_builder; diff --git a/base_layer/core/src/transactions/transaction_components/output_features.rs b/base_layer/core/src/transactions/transaction_components/output_features.rs index d0e40c6f3d..72150df890 100644 --- a/base_layer/core/src/transactions/transaction_components/output_features.rs +++ b/base_layer/core/src/transactions/transaction_components/output_features.rs @@ -37,7 +37,7 @@ use crate::{ consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized, MaxSizeBytes}, transactions::transaction_components::{ AssetOutputFeatures, - CommitteeCheckpointFeatures, + CommitteeDefinitionFeatures, MintNonFungibleFeatures, OutputFlags, SideChainCheckpointFeatures, @@ -60,7 +60,7 @@ pub struct OutputFeatures { pub asset: Option, pub mint_non_fungible: Option, pub sidechain_checkpoint: Option, - pub committee_checkpoint: Option, + pub committee_definition: Option, } impl OutputFeatures { @@ -74,7 +74,7 @@ impl OutputFeatures { asset: Option, mint_non_fungible: Option, sidechain_checkpoint: Option, - committee_checkpoint: Option, + committee_definition: Option, ) -> OutputFeatures { OutputFeatures { version, @@ -86,7 +86,7 @@ impl OutputFeatures { asset, mint_non_fungible, sidechain_checkpoint, - committee_checkpoint, + committee_definition, } } @@ -99,7 +99,7 @@ impl OutputFeatures { asset: Option, mint_non_fungible: Option, sidechain_checkpoint: Option, - committee_checkpoint: Option, + committee_definition: Option, ) -> OutputFeatures { OutputFeatures::new( OutputFeaturesVersion::get_current_version(), @@ -111,7 +111,7 @@ impl OutputFeatures { asset, mint_non_fungible, sidechain_checkpoint, - committee_checkpoint, + committee_definition, ) } @@ -211,11 +211,11 @@ impl OutputFeatures { ) -> OutputFeatures { Self { flags: if is_initial { - OutputFlags::COMMITTEE_CHECKPOINT | OutputFlags::MINT_NON_FUNGIBLE + OutputFlags::COMMITTEE_DEFINITION | OutputFlags::MINT_NON_FUNGIBLE } else { - OutputFlags::COMMITTEE_CHECKPOINT + OutputFlags::COMMITTEE_DEFINITION }, - committee_checkpoint: Some(CommitteeCheckpointFeatures { + committee_definition: Some(CommitteeDefinitionFeatures { committee, effective_sidechain_height, }), @@ -256,7 +256,7 @@ impl ConsensusEncoding for OutputFeatures { match self.version { OutputFeaturesVersion::V0 => (), OutputFeaturesVersion::V1 => { - written += self.committee_checkpoint.consensus_encode(writer)?; + written += self.committee_definition.consensus_encode(writer)?; }, } Ok(written) @@ -281,10 +281,10 @@ impl ConsensusDecoding for OutputFeatures { as ConsensusDecoding>::consensus_decode(reader)?; const MAX_METADATA_SIZE: usize = 1024; let metadata = as ConsensusDecoding>::consensus_decode(reader)?; - let committee_checkpoint = match version { + let committee_definition = match version { OutputFeaturesVersion::V0 => None, OutputFeaturesVersion::V1 => { - as ConsensusDecoding>::consensus_decode(reader)? + as ConsensusDecoding>::consensus_decode(reader)? }, }; Ok(Self { @@ -297,7 +297,7 @@ impl ConsensusDecoding for OutputFeatures { mint_non_fungible, sidechain_checkpoint, metadata: metadata.into(), - committee_checkpoint, + committee_definition, }) } } @@ -364,7 +364,7 @@ mod test { merkle_root: [1u8; 32], committee: iter::repeat_with(PublicKey::default).take(50).collect(), }), - committee_checkpoint: Some(CommitteeCheckpointFeatures { + committee_definition: Some(CommitteeDefinitionFeatures { committee: iter::repeat_with(PublicKey::default).take(50).collect(), effective_sidechain_height: u64::MAX, }), @@ -384,7 +384,7 @@ mod test { subject.asset = None; subject.mint_non_fungible = None; subject.sidechain_checkpoint = None; - subject.committee_checkpoint = None; + subject.committee_definition = None; check_consensus_encoding_correctness(subject).unwrap(); } diff --git a/base_layer/core/src/transactions/transaction_components/output_flags.rs b/base_layer/core/src/transactions/transaction_components/output_flags.rs index 60e203b842..ecc975a9b2 100644 --- a/base_layer/core/src/transactions/transaction_components/output_flags.rs +++ b/base_layer/core/src/transactions/transaction_components/output_flags.rs @@ -39,7 +39,7 @@ bitflags! { const MINT_NON_FUNGIBLE = 0b0000_0100 | Self::NON_FUNGIBLE.bits; const BURN_NON_FUNGIBLE = 0b1000_0000 | Self::NON_FUNGIBLE.bits; const SIDECHAIN_CHECKPOINT = 0b0001_0000 | Self::NON_FUNGIBLE.bits; - const COMMITTEE_CHECKPOINT = 0b0010_0000 | Self::NON_FUNGIBLE.bits; + const COMMITTEE_DEFINITION = 0b0010_0000 | Self::NON_FUNGIBLE.bits; } } diff --git a/base_layer/wallet/src/assets/asset_manager.rs b/base_layer/wallet/src/assets/asset_manager.rs index 7f9e486e11..ca042a49f7 100644 --- a/base_layer/wallet/src/assets/asset_manager.rs +++ b/base_layer/wallet/src/assets/asset_manager.rs @@ -244,7 +244,7 @@ impl AssetManager { Ok((tx_id, transaction)) } - pub async fn create_committee_checkpoint( + pub async fn create_committee_definition( &mut self, asset_public_key: PublicKey, committee_pub_keys: Vec, diff --git a/base_layer/wallet/src/assets/asset_manager_handle.rs b/base_layer/wallet/src/assets/asset_manager_handle.rs index 32dab1df1b..893c427e54 100644 --- a/base_layer/wallet/src/assets/asset_manager_handle.rs +++ b/base_layer/wallet/src/assets/asset_manager_handle.rs @@ -117,7 +117,7 @@ impl AssetManagerHandle { } } - pub async fn create_committee_checkpoint( + pub async fn create_committee_definition( &mut self, public_key: &PublicKey, committee_public_keys: &[PublicKey], @@ -134,7 +134,7 @@ impl AssetManagerHandle { { AssetManagerResponse::CreateCommitteeCheckpoint { transaction, tx_id } => Ok((tx_id, *transaction)), _ => Err(WalletError::UnexpectedApiResponse { - method: "create_committee_checkpoint".to_string(), + method: "create_committee_definition".to_string(), api: "AssetManagerService".to_string(), }), } diff --git a/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs b/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs index e9a8a600f1..f0ba78c182 100644 --- a/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs +++ b/base_layer/wallet/src/assets/infrastructure/asset_manager_service.rs @@ -166,7 +166,7 @@ impl AssetManagerService { } => { let (tx_id, transaction) = self .manager - .create_committee_checkpoint(*asset_public_key, committee_public_keys, effective_sidechain_height) + .create_committee_definition(*asset_public_key, committee_public_keys, effective_sidechain_height) .await?; Ok(AssetManagerResponse::CreateCommitteeCheckpoint { transaction: Box::new(transaction), diff --git a/integration_tests/features/support/wallet_cli_steps.js b/integration_tests/features/support/wallet_cli_steps.js index d830144553..1d54d550ca 100644 --- a/integration_tests/features/support/wallet_cli_steps.js +++ b/integration_tests/features/support/wallet_cli_steps.js @@ -271,7 +271,7 @@ Then( let wallet = this.getWallet(wallet_name); let output = await wallet_run_command( wallet, - `create-committee-checkpoint ${this.asset_public_key} ${member}` + `create-committee-definition ${this.asset_public_key} ${member}` ); // console.log(output.buffer); expect(output.buffer).to.have.string(" committee members"); From d34af75b292aebc0ca2aca2a48bd9876204465de Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Wed, 16 Feb 2022 15:14:41 +0200 Subject: [PATCH 6/9] feat: mempool validation for versions --- .../tests/blockchain_database.rs | 4 + .../core/src/consensus/consensus_constants.rs | 76 ++++++++- .../core/src/transactions/test_helpers.rs | 33 +++- .../output_features_version.rs | 4 +- .../transaction_input_version.rs | 4 +- .../transaction_kernel_version.rs | 2 +- .../transaction_output_version.rs | 2 +- .../unblinded_output.rs | 6 +- .../transaction_initializer.rs | 1 - .../src/validation/transaction_validators.rs | 63 +++++++ base_layer/core/tests/mempool.rs | 160 +++++++++++++++++- 11 files changed, 338 insertions(+), 17 deletions(-) diff --git a/base_layer/core/src/chain_storage/tests/blockchain_database.rs b/base_layer/core/src/chain_storage/tests/blockchain_database.rs index ea825f0f8e..9932f4c72f 100644 --- a/base_layer/core/src/chain_storage/tests/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/tests/blockchain_database.rs @@ -411,6 +411,8 @@ mod add_block { script: tari_crypto::script![Nop], covenant: Default::default(), input_data: None, + input_version: None, + output_version: None, }]); let commitment_hex = txns[0] .body @@ -450,6 +452,8 @@ mod add_block { script: tari_crypto::script![Nop], covenant: Default::default(), input_data: None, + input_version: None, + output_version: None, }]); let (block, _) = create_next_block(&db, &prev_block, txns); diff --git a/base_layer/core/src/consensus/consensus_constants.rs b/base_layer/core/src/consensus/consensus_constants.rs index 4da890d10d..3bf63c8e77 100644 --- a/base_layer/core/src/consensus/consensus_constants.rs +++ b/base_layer/core/src/consensus/consensus_constants.rs @@ -20,7 +20,10 @@ // 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::{collections::HashMap, ops::Add}; +use std::{ + collections::HashMap, + ops::{Add, RangeInclusive}, +}; use chrono::{DateTime, Duration, Utc}; use tari_common::configuration::Network; @@ -31,7 +34,13 @@ use crate::{ proof_of_work::{Difficulty, PowAlgorithm}, transactions::{ tari_amount::{uT, MicroTari, T}, - transaction_components::OutputFeatures, + transaction_components::{ + OutputFeatures, + OutputFeaturesVersion, + TransactionInputVersion, + TransactionKernelVersion, + TransactionOutputVersion, + }, weight::TransactionWeight, }, }; @@ -72,6 +81,35 @@ pub struct ConsensusConstants { transaction_weight: TransactionWeight, /// Maximum byte size of TariScript max_script_byte_size: usize, + /// Range of valid transaction input versions + pub(crate) input_version_range: RangeInclusive, + /// Range of valid transaction output (and features) versions + pub(crate) output_version_range: OutputVersionRange, + /// Range of valid transaction kernel versions + pub(crate) kernel_version_range: RangeInclusive, +} + +// todo: remove this once OutputFeaturesVersion is removed in favor of just TransactionOutputVersion +#[derive(Debug, Clone)] +pub struct OutputVersionRange { + pub outputs: RangeInclusive, + pub features: RangeInclusive, +} + +/// All V0 for Inputs, Outputs + Features, Kernels +fn version_zero() -> ( + RangeInclusive, + OutputVersionRange, + RangeInclusive, +) { + let input_version_range = TransactionInputVersion::V0..=TransactionInputVersion::V0; + let kernel_version_range = TransactionKernelVersion::V0..=TransactionKernelVersion::V0; + let output_version_range = OutputVersionRange { + outputs: TransactionOutputVersion::V0..=TransactionOutputVersion::V0, + features: OutputFeaturesVersion::V0..=OutputFeaturesVersion::V0, + }; + + (input_version_range, output_version_range, kernel_version_range) } /// This is just a convenience wrapper to put all the info into a hashmap per diff algo @@ -109,7 +147,7 @@ impl ConsensusConstants { self.blockchain_version } - /// This returns the FTL(Future Time Limit) for blocks + /// This returns the FTL (Future Time Limit) for blocks. /// Any block with a timestamp greater than this is rejected. pub fn ftl(&self) -> EpochTime { (Utc::now() @@ -210,6 +248,18 @@ impl ConsensusConstants { &self.transaction_weight } + pub fn input_version_range(&self) -> &RangeInclusive { + &self.input_version_range + } + + pub fn output_version_range(&self) -> &OutputVersionRange { + &self.output_version_range + } + + pub fn kernel_version_range(&self) -> &RangeInclusive { + &self.kernel_version_range + } + pub fn localnet() -> Vec { let difficulty_block_window = 90; let mut algos = HashMap::new(); @@ -225,6 +275,7 @@ impl ConsensusConstants { max_difficulty: 1.into(), target_time: 200, }); + let (input_version_range, output_version_range, kernel_version_range) = version_zero(); vec![ConsensusConstants { effective_from_height: 0, coinbase_lock_height: 2, @@ -241,6 +292,9 @@ impl ConsensusConstants { faucet_value: (5000 * 4000) * T, transaction_weight: TransactionWeight::latest(), max_script_byte_size: 2048, + input_version_range, + output_version_range, + kernel_version_range, }] } @@ -259,6 +313,7 @@ impl ConsensusConstants { max_difficulty: u64::MAX.into(), target_time: 200, }); + let (input_version_range, output_version_range, kernel_version_range) = version_zero(); vec![ConsensusConstants { effective_from_height: 0, coinbase_lock_height: 6, @@ -275,6 +330,9 @@ impl ConsensusConstants { faucet_value: (5000 * 4000) * T, transaction_weight: TransactionWeight::v1(), max_script_byte_size: 2048, + input_version_range, + output_version_range, + kernel_version_range, }] } @@ -293,6 +351,7 @@ impl ConsensusConstants { max_difficulty: u64::MAX.into(), target_time: 200, }); + let (input_version_range, output_version_range, kernel_version_range) = version_zero(); vec![ConsensusConstants { effective_from_height: 0, coinbase_lock_height: 6, @@ -312,6 +371,9 @@ impl ConsensusConstants { faucet_value: (5000 * 4000) * T, transaction_weight: TransactionWeight::v2(), max_script_byte_size: 2048, + input_version_range, + output_version_range, + kernel_version_range, }] } @@ -336,6 +398,7 @@ impl ConsensusConstants { max_difficulty: u64::MAX.into(), target_time: 200, }); + let (input_version_range, output_version_range, kernel_version_range) = version_zero(); vec![ConsensusConstants { effective_from_height: 0, coinbase_lock_height: 360, @@ -355,6 +418,9 @@ impl ConsensusConstants { faucet_value: (10 * 4000) * T, transaction_weight: TransactionWeight::v2(), max_script_byte_size: 2048, + input_version_range, + output_version_range, + kernel_version_range, }] } @@ -374,6 +440,7 @@ impl ConsensusConstants { max_difficulty: u64::MAX.into(), target_time: 200, }); + let (input_version_range, output_version_range, kernel_version_range) = version_zero(); vec![ConsensusConstants { effective_from_height: 0, coinbase_lock_height: 1, @@ -390,6 +457,9 @@ impl ConsensusConstants { faucet_value: MicroTari::from(0), transaction_weight: TransactionWeight::v2(), max_script_byte_size: 2048, + input_version_range, + output_version_range, + kernel_version_range, }] } } diff --git a/base_layer/core/src/transactions/test_helpers.rs b/base_layer/core/src/transactions/test_helpers.rs index dab1cb233d..e0afd0af9e 100644 --- a/base_layer/core/src/transactions/test_helpers.rs +++ b/base_layer/core/src/transactions/test_helpers.rs @@ -35,6 +35,7 @@ use tari_crypto::{ script::{ExecutionStack, TariScript}, }; +use super::transaction_components::{TransactionInputVersion, TransactionOutputVersion}; use crate::{ consensus::{ConsensusEncodingSized, ConsensusManager}, covenants::Covenant, @@ -97,6 +98,16 @@ pub struct UtxoTestParams { pub features: OutputFeatures, pub input_data: Option, pub covenant: Covenant, + pub output_version: Option, +} + +impl UtxoTestParams { + pub fn with_value(value: MicroTari) -> Self { + Self { + value, + ..Default::default() + } + } } impl Default for UtxoTestParams { @@ -107,6 +118,7 @@ impl Default for UtxoTestParams { features: Default::default(), input_data: None, covenant: Covenant::default(), + output_version: None, } } } @@ -150,7 +162,10 @@ impl TestParams { ) .unwrap(); - UnblindedOutput::new_current_version( + UnblindedOutput::new( + params + .output_version + .unwrap_or(TransactionOutputVersion::get_current_version()), params.value, self.spend_key.clone(), params.features, @@ -307,6 +322,8 @@ macro_rules! txn_schema { script: tari_crypto::script![Nop], covenant: Default::default(), input_data: None, + input_version: None, + output_version: None, } }}; @@ -319,7 +336,8 @@ macro_rules! txn_schema { features: $features.clone() ) }}; - (from: $input:expr, to: $outputs:expr, features: $features:expr) => {{ + + (from: $input:expr, to: $outputs:expr, features: $features:expr) => {{ txn_schema!( from: $input, to:$outputs, @@ -328,6 +346,7 @@ macro_rules! txn_schema { features: $features ) }}; + (from: $input:expr, to: $outputs:expr, fee: $fee:expr) => { txn_schema!( from: $input, @@ -361,6 +380,8 @@ pub struct TransactionSchema { pub script: TariScript, pub input_data: Option, pub covenant: Covenant, + pub input_version: Option, + pub output_version: Option, } /// Create an unconfirmed transaction for testing with a valid fee, unique access_sig, random inputs and outputs, the @@ -500,7 +521,7 @@ pub fn create_sender_transaction_protocol_with( Ok(stx_protocol) } -/// Spend the provided UTXOs by to the given amounts. Change will be created with any outstanding amount. +/// Spend the provided UTXOs to the given amounts. Change will be created with any outstanding amount. /// You only need to provide the unblinded outputs to spend. This function will calculate the commitment for you. /// This is obviously less efficient, but is offered as a convenience. /// The output features will be applied to every output @@ -537,9 +558,12 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto for tx_input in &schema.from { let input = tx_input.clone(); - let utxo = input + let mut utxo = input .as_transaction_input(&factories.commitment) .expect("Should be able to make a transaction input"); + utxo.version = schema + .input_version + .unwrap_or(TransactionInputVersion::get_current_version()); stx_builder.with_input(utxo, input.clone()); } let mut outputs = Vec::with_capacity(schema.to.len()); @@ -551,6 +575,7 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto script: schema.script.clone(), input_data: schema.input_data.clone(), covenant: schema.covenant.clone(), + output_version: None, }); outputs.push(utxo.clone()); stx_builder diff --git a/base_layer/core/src/transactions/transaction_components/output_features_version.rs b/base_layer/core/src/transactions/transaction_components/output_features_version.rs index a937d17a77..df0e5a6118 100644 --- a/base_layer/core/src/transactions/transaction_components/output_features_version.rs +++ b/base_layer/core/src/transactions/transaction_components/output_features_version.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized}; -#[derive(Debug, Clone, Copy, Hash, PartialEq, Deserialize, Serialize, Eq)] +#[derive(Debug, Clone, Copy, Hash, PartialEq, Deserialize, Serialize, Eq, PartialOrd)] #[repr(u8)] pub enum OutputFeaturesVersion { V0 = 0, @@ -17,7 +17,7 @@ pub enum OutputFeaturesVersion { impl OutputFeaturesVersion { pub fn get_current_version() -> Self { - Self::V1 + Self::V0 } pub fn as_u8(self) -> u8 { diff --git a/base_layer/core/src/transactions/transaction_components/transaction_input_version.rs b/base_layer/core/src/transactions/transaction_components/transaction_input_version.rs index ce31e72768..ced4f6d081 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_input_version.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_input_version.rs @@ -8,10 +8,11 @@ use serde::{Deserialize, Serialize}; use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized}; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd)] #[repr(u8)] pub enum TransactionInputVersion { V0 = 0, + V1 = 1, } impl TransactionInputVersion { @@ -30,6 +31,7 @@ impl TryFrom for TransactionInputVersion { fn try_from(value: u8) -> Result { match value { 0 => Ok(TransactionInputVersion::V0), + 1 => Ok(TransactionInputVersion::V1), _ => Err("Unknown version!".to_string()), } } diff --git a/base_layer/core/src/transactions/transaction_components/transaction_kernel_version.rs b/base_layer/core/src/transactions/transaction_components/transaction_kernel_version.rs index 15efe2c8ac..4cc58ea258 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_kernel_version.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_kernel_version.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized}; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd)] #[repr(u8)] pub enum TransactionKernelVersion { V0 = 0, diff --git a/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs b/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs index 4a8bc1ba2b..96a390d613 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_output_version.rs @@ -33,7 +33,7 @@ use serde::{Deserialize, Serialize}; use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized}; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd)] #[repr(u8)] pub enum TransactionOutputVersion { V0 = 0, diff --git a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs index 49beb99757..9a430cf654 100644 --- a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs +++ b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs @@ -196,7 +196,8 @@ impl UnblindedOutput { )); } let commitment = factories.commitment.commit(&self.spending_key, &self.value.into()); - let output = TransactionOutput::new_current_version( + let output = TransactionOutput::new( + self.version.clone(), self.features.clone(), commitment, RangeProof::from_bytes( @@ -242,7 +243,8 @@ impl UnblindedOutput { .map_err(|_| TransactionError::RangeProofError(RangeProofError::ProofConstructionError))? }; - let output = TransactionOutput::new_current_version( + let output = TransactionOutput::new( + self.version.clone(), self.features.clone(), commitment, proof, diff --git a/base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs b/base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs index 7a500c03d9..27420de105 100644 --- a/base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs +++ b/base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs @@ -496,7 +496,6 @@ impl SenderTransactionInitializer { } // Create transaction outputs - let mut outputs = match self .sender_custom_outputs .iter() diff --git a/base_layer/core/src/validation/transaction_validators.rs b/base_layer/core/src/validation/transaction_validators.rs index 7d3991fc12..ad68993ae1 100644 --- a/base_layer/core/src/validation/transaction_validators.rs +++ b/base_layer/core/src/validation/transaction_validators.rs @@ -25,6 +25,7 @@ use tari_utilities::hex::Hex; use crate::{ chain_storage::{BlockchainBackend, BlockchainDatabase, PrunedOutput}, + consensus::ConsensusConstants, transactions::{ transaction_components::{SpentOutput, Transaction}, CryptoFactories, @@ -83,6 +84,7 @@ impl MempoolTransactionValidation for TxInternalConsistenc /// This validator will check the transaction against the current consensus rules. /// /// 1. The transaction weight should not exceed the maximum weight for 1 block +/// 1. Input, output, and kernel versions are valid according to consensus /// 1. All of the outputs should have a unique asset id in the transaction /// 1. All of the outputs should have a unique asset id not already on chain (unless spent to a new output) #[derive(Clone)] @@ -95,6 +97,65 @@ impl TxConsensusValidator { Self { db } } + fn validate_versions( + &self, + tx: &Transaction, + consensus_constants: &ConsensusConstants, + ) -> Result<(), ValidationError> { + // validate input version + for input in tx.body().inputs() { + if !consensus_constants.input_version_range.contains(&input.version) { + let msg = format!( + "Transaction input contains a version not allowed by consensus ({:?})", + input.version + ); + return Err(ValidationError::ConsensusError(msg)); + } + } + + // validate output version and output features version + for output in tx.body().outputs() { + let valid_output_version = consensus_constants + .output_version_range + .outputs + .contains(&output.version); + + let valid_features_version = consensus_constants + .output_version_range + .features + .contains(&output.features.version); + + if !valid_output_version { + let msg = format!( + "Transaction output version is not allowed by consensus ({:?})", + output.version + ); + return Err(ValidationError::ConsensusError(msg)); + } + + if !valid_features_version { + let msg = format!( + "Transaction output features version is not allowed by consensus ({:?})", + output.features.version + ); + return Err(ValidationError::ConsensusError(msg)); + } + } + + // validate kernel version + for kernel in tx.body().kernels() { + if !consensus_constants.kernel_version_range.contains(&kernel.version) { + let msg = format!( + "Transaction kernel version is not allowed by consensus ({:?})", + kernel.version + ); + return Err(ValidationError::ConsensusError(msg)); + } + } + + Ok(()) + } + fn validate_unique_asset_rules(&self, tx: &Transaction) -> Result<(), ValidationError> { let outputs = tx.body.outputs(); @@ -163,6 +224,8 @@ impl MempoolTransactionValidation for TxConsensusValidator return Err(ValidationError::MaxTransactionWeightExceeded); } + self.validate_versions(tx, consensus_constants)?; + self.validate_unique_asset_rules(tx) } } diff --git a/base_layer/core/tests/mempool.rs b/base_layer/core/tests/mempool.rs index b6634719dc..4faf17ee05 100644 --- a/base_layer/core/tests/mempool.rs +++ b/base_layer/core/tests/mempool.rs @@ -50,7 +50,14 @@ use tari_core::{ transactions::{ fee::Fee, tari_amount::{uT, MicroTari, T}, - test_helpers::{create_unblinded_output, schema_to_transaction, spend_utxos, TestParams}, + test_helpers::{ + create_unblinded_output, + schema_to_transaction, + spend_utxos, + TestParams, + TransactionSchema, + UtxoTestParams, + }, transaction_components::{KernelBuilder, OutputFeatures, OutputFlags, Transaction, TransactionOutput}, transaction_protocol::{build_challenge, TransactionMetadata}, CryptoFactories, @@ -992,6 +999,156 @@ async fn consensus_validation_large_tx() { // make sure the tx was not accepted into the mempool assert!(matches!(response, TxStorageResponse::NotStored)); } +#[tokio::test] +#[allow(clippy::erasing_op)] +#[allow(clippy::identity_op)] +async fn consensus_validation_versions() { + use tari_core::transactions::transaction_components::{ + OutputFeaturesVersion, + TransactionInputVersion, + TransactionKernelVersion, + TransactionOutputVersion, + }; + + let network = Network::LocalNet; + let (mut store, mut blocks, mut outputs, consensus_manager) = create_new_blockchain(network); + let cc = consensus_manager.consensus_constants(0); + + // check the current localnet defaults + assert_eq!( + cc.input_version_range().clone(), + TransactionInputVersion::V0..=TransactionInputVersion::V0 + ); + assert_eq!( + cc.kernel_version_range().clone(), + TransactionKernelVersion::V0..=TransactionKernelVersion::V0 + ); + assert_eq!( + cc.output_version_range().clone().outputs, + TransactionOutputVersion::V0..=TransactionOutputVersion::V0 + ); + assert_eq!( + cc.output_version_range().clone().features, + OutputFeaturesVersion::V0..=OutputFeaturesVersion::V0 + ); + + let mempool_validator = TxConsensusValidator::new(store.clone()); + + let mempool = Mempool::new( + MempoolConfig::default(), + consensus_manager.clone(), + Box::new(mempool_validator), + ); + + let test_params = TestParams::new(); + let params = UtxoTestParams::with_value(1 * T); + let output_v0_features_v0 = test_params.create_unblinded_output(params); + assert_eq!(output_v0_features_v0.version, TransactionOutputVersion::V0); + assert_eq!(output_v0_features_v0.features.version, OutputFeaturesVersion::V0); + + let test_params = TestParams::new(); + let params = UtxoTestParams::with_value(1 * T); + let mut output_v1_features_v0 = test_params.create_unblinded_output(params); + output_v1_features_v0.version = TransactionOutputVersion::V1; + assert_eq!(output_v1_features_v0.version, TransactionOutputVersion::V1); + assert_eq!(output_v1_features_v0.features.version, OutputFeaturesVersion::V0); + + let features = OutputFeatures::new( + OutputFeaturesVersion::V1, + OutputFlags::empty(), + 0, + Default::default(), + None, + None, + None, + None, + None, + None, + ); + + let test_params = TestParams::new(); + let mut params = UtxoTestParams::with_value(1 * T); + params.features = features.clone(); + let output_v0_features_v1 = test_params.create_unblinded_output(params); + assert_eq!(output_v0_features_v1.version, TransactionOutputVersion::V0); + assert_eq!(output_v0_features_v1.features.version, OutputFeaturesVersion::V1); + + let test_params = TestParams::new(); + let mut params = UtxoTestParams::with_value(1 * T); + params.features = features.clone(); + let mut output_v1_features_v1 = test_params.create_unblinded_output(params); + output_v1_features_v1.version = TransactionOutputVersion::V1; + assert_eq!(output_v1_features_v1.version, TransactionOutputVersion::V1); + assert_eq!(output_v1_features_v1.features.version, OutputFeaturesVersion::V1); + + let schema = txn_schema!( + from: vec![outputs[0][0].clone()], + to: vec![2 * T, 2 * T, 2 * T, 2 * T, 2 * T] + ); + let txs = vec![schema]; + generate_new_block(&mut store, &mut blocks, &mut outputs, txs, &consensus_manager).unwrap(); + + // Cases: + // invalid input version + let tx = TransactionSchema { + from: vec![outputs[1][0].clone()], + to: vec![1 * T], + to_outputs: vec![], + fee: 25.into(), + lock_height: 0, + features: Default::default(), + script: tari_crypto::script![Nop], + input_data: None, + covenant: Default::default(), + input_version: Some(TransactionInputVersion::V1), + output_version: None, + }; + + let (tx, _) = spend_utxos(tx); + let tx = Arc::new(tx); + let response = mempool.insert(tx).await.unwrap(); + assert!(matches!(response, TxStorageResponse::NotStoredConsensus)); + + // invalid output version + let tx = TransactionSchema { + from: vec![outputs[1][1].clone()], + to: vec![], + to_outputs: vec![output_v1_features_v0], + fee: 25.into(), + lock_height: 0, + features: Default::default(), + script: tari_crypto::script![Nop], + input_data: None, + covenant: Default::default(), + input_version: None, + output_version: Some(TransactionOutputVersion::V1), + }; + + let (tx, _) = spend_utxos(tx); + let tx = Arc::new(tx); + let response = mempool.insert(tx).await.unwrap(); + assert!(matches!(response, TxStorageResponse::NotStoredConsensus)); + + // invalid output features version + let tx = TransactionSchema { + from: vec![outputs[1][2].clone()], + to: vec![], + to_outputs: vec![output_v0_features_v1], + fee: 25.into(), + lock_height: 0, + features: Default::default(), + script: tari_crypto::script![Nop], + input_data: None, + covenant: Default::default(), + input_version: None, + output_version: None, + }; + + let (tx, _) = spend_utxos(tx); + let tx = Arc::new(tx); + let response = mempool.insert(tx).await.unwrap(); + assert!(matches!(response, TxStorageResponse::NotStoredConsensus)); +} #[tokio::test] #[allow(clippy::erasing_op)] @@ -1100,7 +1257,6 @@ async fn consensus_validation_unique_id() { let (tx, _) = spend_utxos(tx); let tx = Arc::new(tx); let response = mempool.insert(tx).await.unwrap(); - dbg!(&response); assert!(matches!(response, TxStorageResponse::NotStoredConsensus)); } From cf9b7e91bd3bac6951834853f7c0e8b44ad13419 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Wed, 16 Feb 2022 15:34:17 +0200 Subject: [PATCH 7/9] =?UTF-8?q?=F0=9F=85=B1=EF=B8=8Flippy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base_layer/core/src/transactions/test_helpers.rs | 4 ++-- .../transactions/transaction_components/unblinded_output.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/base_layer/core/src/transactions/test_helpers.rs b/base_layer/core/src/transactions/test_helpers.rs index e0afd0af9e..fef1ce910e 100644 --- a/base_layer/core/src/transactions/test_helpers.rs +++ b/base_layer/core/src/transactions/test_helpers.rs @@ -165,7 +165,7 @@ impl TestParams { UnblindedOutput::new( params .output_version - .unwrap_or(TransactionOutputVersion::get_current_version()), + .unwrap_or_else(TransactionOutputVersion::get_current_version), params.value, self.spend_key.clone(), params.features, @@ -563,7 +563,7 @@ pub fn create_stx_protocol(schema: TransactionSchema) -> (SenderTransactionProto .expect("Should be able to make a transaction input"); utxo.version = schema .input_version - .unwrap_or(TransactionInputVersion::get_current_version()); + .unwrap_or_else(TransactionInputVersion::get_current_version); stx_builder.with_input(utxo, input.clone()); } let mut outputs = Vec::with_capacity(schema.to.len()); diff --git a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs index 9a430cf654..78237cd270 100644 --- a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs +++ b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs @@ -197,7 +197,7 @@ impl UnblindedOutput { } let commitment = factories.commitment.commit(&self.spending_key, &self.value.into()); let output = TransactionOutput::new( - self.version.clone(), + self.version, self.features.clone(), commitment, RangeProof::from_bytes( @@ -244,7 +244,7 @@ impl UnblindedOutput { }; let output = TransactionOutput::new( - self.version.clone(), + self.version, self.features.clone(), commitment, proof, From 8e4993228782419803e096035d8db93c950fd971 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Thu, 17 Feb 2022 10:04:17 +0200 Subject: [PATCH 8/9] fix:tests --- .../transaction_components/output_features.rs | 8 ++++++- .../transaction_components/test.rs | 24 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/base_layer/core/src/transactions/transaction_components/output_features.rs b/base_layer/core/src/transactions/transaction_components/output_features.rs index 72150df890..e4b451b755 100644 --- a/base_layer/core/src/transactions/transaction_components/output_features.rs +++ b/base_layer/core/src/transactions/transaction_components/output_features.rs @@ -339,7 +339,7 @@ mod test { fn make_fully_populated_output_features() -> OutputFeatures { OutputFeatures { - version: OutputFeaturesVersion::get_current_version(), + version: OutputFeaturesVersion::V1, flags: OutputFlags::all(), maturity: u64::MAX, metadata: vec![1; 1024], @@ -373,6 +373,12 @@ mod test { #[test] fn it_encodes_and_decodes_correctly() { + // v0 committee_definition decodes to None + let mut subject = make_fully_populated_output_features(); + subject.version = OutputFeaturesVersion::V0; + subject.committee_definition = None; + check_consensus_encoding_correctness(subject).unwrap(); + let subject = make_fully_populated_output_features(); check_consensus_encoding_correctness(subject).unwrap(); } diff --git a/base_layer/core/src/transactions/transaction_components/test.rs b/base_layer/core/src/transactions/transaction_components/test.rs index d4e0499c54..3ac69317e7 100644 --- a/base_layer/core/src/transactions/transaction_components/test.rs +++ b/base_layer/core/src/transactions/transaction_components/test.rs @@ -441,7 +441,15 @@ mod output_features { #[test] fn consensus_encode_minimal() { - let features = OutputFeatures::with_maturity(0); + let mut features = OutputFeatures::default(); + features.version = OutputFeaturesVersion::V0; + let mut buf = Vec::new(); + let written = features.consensus_encode(&mut buf).unwrap(); + assert_eq!(buf.len(), 9); + assert_eq!(written, 9); + + let mut features = OutputFeatures::default(); + features.version = OutputFeaturesVersion::V1; let mut buf = Vec::new(); let written = features.consensus_encode(&mut buf).unwrap(); assert_eq!(buf.len(), 10); @@ -450,7 +458,19 @@ mod output_features { #[test] fn consensus_encode_decode() { - let features = OutputFeatures::create_coinbase(u64::MAX); + let mut features = OutputFeatures::create_coinbase(u64::MAX); + features.version = OutputFeaturesVersion::V0; + let known_size = features.consensus_encode_exact_size(); + let mut buf = Vec::with_capacity(known_size); + assert_eq!(known_size, 18); + let written = features.consensus_encode(&mut buf).unwrap(); + assert_eq!(buf.len(), 18); + assert_eq!(written, 18); + let decoded_features = OutputFeatures::consensus_decode(&mut &buf[..]).unwrap(); + assert_eq!(features, decoded_features); + + let mut features = OutputFeatures::create_coinbase(u64::MAX); + features.version = OutputFeaturesVersion::V1; let known_size = features.consensus_encode_exact_size(); let mut buf = Vec::with_capacity(known_size); assert_eq!(known_size, 19); From d654044034f0be816b3226c0eee3015f64ca40a5 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Thu, 17 Feb 2022 10:17:40 +0200 Subject: [PATCH 9/9] clippy --- base_layer/core/src/transactions/transaction_components/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/base_layer/core/src/transactions/transaction_components/test.rs b/base_layer/core/src/transactions/transaction_components/test.rs index 3ac69317e7..aed73614d1 100644 --- a/base_layer/core/src/transactions/transaction_components/test.rs +++ b/base_layer/core/src/transactions/transaction_components/test.rs @@ -440,6 +440,7 @@ mod output_features { use crate::consensus::{ConsensusDecoding, ConsensusEncoding, ConsensusEncodingSized}; #[test] + #[allow(clippy::field_reassign_with_default)] fn consensus_encode_minimal() { let mut features = OutputFeatures::default(); features.version = OutputFeaturesVersion::V0;