From 1b33a7dcae288deb5574ce80da76e61670941cd3 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 8 Aug 2024 17:32:11 +0200 Subject: [PATCH] wip --- Cargo.lock | 6 ++ .../minotari_ledger_wallet/common/Cargo.toml | 14 ++++ .../common/src/borsch.rs | 62 +++++++++++++++++ .../common/src/common_types.rs | 21 +----- .../minotari_ledger_wallet/common/src/lib.rs | 28 ++------ .../common/src/network.rs | 67 +++++++++++++++++++ .../common/src/utils.rs | 52 ++++++++------ .../minotari_ledger_wallet/comms/Cargo.toml | 3 + .../minotari_ledger_wallet/comms/src/lib.rs | 63 +++++++++++++++++ common/src/configuration/network.rs | 1 + infrastructure/tari_script/Cargo.toml | 1 + 11 files changed, 255 insertions(+), 63 deletions(-) create mode 100644 applications/minotari_ledger_wallet/common/src/borsch.rs create mode 100644 applications/minotari_ledger_wallet/common/src/network.rs diff --git a/Cargo.lock b/Cargo.lock index f8b4163b9e5..e61663ac483 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3355,11 +3355,16 @@ dependencies = [ [[package]] name = "minotari_ledger_wallet_common" version = "1.1.0-pre.2" +dependencies = [ + "borsh", + "tari_script", +] [[package]] name = "minotari_ledger_wallet_comms" version = "1.1.0-pre.2" dependencies = [ + "borsh", "dialoguer 0.11.0", "ledger-transport 0.10.0 (git+https://github.com/Zondax/ledger-rs?rev=20e2a20)", "ledger-transport-hid", @@ -6461,6 +6466,7 @@ dependencies = [ "blake2", "borsh", "digest 0.10.7", + "hex", "integer-encoding", "rand", "serde", diff --git a/applications/minotari_ledger_wallet/common/Cargo.toml b/applications/minotari_ledger_wallet/common/Cargo.toml index 4855d177fc6..f5f4cc1c71b 100644 --- a/applications/minotari_ledger_wallet/common/Cargo.toml +++ b/applications/minotari_ledger_wallet/common/Cargo.toml @@ -6,3 +6,17 @@ license = "BSD-3-Clause" edition = "2021" [dependencies] +#tari_crypto = { version = "0.20.3", default-features = false, features = ["borsh"]} +#tari_hashing = { path = "../../../hashing", version = "1.1.0-pre.2" } + +#blake2 = { version = "0.10", default-features = false } +borsh = { version = "1.2", default-features = false, features = ["unstable__schema"] } +#digest = { version = "0.10", default-features = false } +#embedded-alloc = "0.5.0" +#spin = "0.9.8" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tari_target_network_mainnet)', 'cfg(tari_target_network_nextnet)'] } + +[dev-dependencies] +tari_script = { path = "../../../infrastructure/tari_script", version = "1.1.0-pre.2" } diff --git a/applications/minotari_ledger_wallet/common/src/borsch.rs b/applications/minotari_ledger_wallet/common/src/borsch.rs new file mode 100644 index 00000000000..51a2bc04cd9 --- /dev/null +++ b/applications/minotari_ledger_wallet/common/src/borsch.rs @@ -0,0 +1,62 @@ +// Copyright 2024 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use core::result::Result; + +use borsh::{io::Write, BorshDeserialize, BorshSerialize}; + +// Define custom error types to replace std::io::Error +#[derive(Debug)] +pub struct DeserializeError; + +#[derive(Debug)] +pub struct SerializeError; + +pub trait FromBytes { + fn borsh_from_bytes(buf: &mut &[u8]) -> Result; +} + +impl FromBytes for T { + fn borsh_from_bytes(buf: &mut &[u8]) -> Result { + T::deserialize(buf).map_err(|_| DeserializeError) + } +} + +pub trait SerializedSize { + fn get_serialized_size(&self) -> Result; +} + +impl SerializedSize for T { + fn get_serialized_size(&self) -> Result { + let mut counter = ByteCounter::new(); + self.serialize(&mut counter).map_err(|_| SerializeError)?; + Ok(counter.get()) + } +} + +#[derive(Debug, Clone, Default)] +pub struct ByteCounter { + count: usize, +} + +impl ByteCounter { + pub fn new() -> Self { + Default::default() + } + + pub fn get(&self) -> usize { + self.count + } +} + +impl Write for ByteCounter { + fn write(&mut self, buf: &[u8]) -> Result { + let len = buf.len(); + self.count += len; + Ok(len) + } + + fn flush(&mut self) -> Result<(), borsh::io::Error> { + Ok(()) + } +} diff --git a/applications/minotari_ledger_wallet/common/src/common_types.rs b/applications/minotari_ledger_wallet/common/src/common_types.rs index 6409286c106..be39cc81f71 100644 --- a/applications/minotari_ledger_wallet/common/src/common_types.rs +++ b/applications/minotari_ledger_wallet/common/src/common_types.rs @@ -1,24 +1,5 @@ // Copyright 2024 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. +// SPDX-License-Identifier: BSD-3-Clause use alloc::string::String; diff --git a/applications/minotari_ledger_wallet/common/src/lib.rs b/applications/minotari_ledger_wallet/common/src/lib.rs index 63906a10009..b26a2f63758 100644 --- a/applications/minotari_ledger_wallet/common/src/lib.rs +++ b/applications/minotari_ledger_wallet/common/src/lib.rs @@ -1,31 +1,17 @@ -// Copyright 2024 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. +// Copyright 2024 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause #![no_std] +#![no_main] +#![feature(alloc_error_handler)] //! # Common types shared by the Ledger application and the rest of the Tari codebase. /// Note: `ledger-device-rust-sdk` cannot be included in this crate as it can only be compiled for no-std and the /// rest of the Tari code base is compiled for std. extern crate alloc; +pub mod borsch; pub mod common_types; +pub mod network; mod utils; +pub use utils::{hex_to_bytes_serialized, PUSH_PUBKEY_IDENTIFIER}; diff --git a/applications/minotari_ledger_wallet/common/src/network.rs b/applications/minotari_ledger_wallet/common/src/network.rs new file mode 100644 index 00000000000..8a969468f66 --- /dev/null +++ b/applications/minotari_ledger_wallet/common/src/network.rs @@ -0,0 +1,67 @@ +// Copyright 2024 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +/// Represents the available Tari p2p networks. Only nodes with matching byte values will be able to connect, so these +/// should never be changed once released. +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum Network { + MainNet = 0x00, + StageNet = 0x01, + NextNet = 0x02, + LocalNet = 0x10, + Igor = 0x24, + Esmeralda = 0x26, +} + +impl Network { + pub fn as_byte(self) -> u8 { + self as u8 + } + + pub const fn as_key_str(self) -> &'static str { + #[allow(clippy::enum_glob_use)] + use Network::*; + match self { + MainNet => "mainnet", + StageNet => "stagenet", + NextNet => "nextnet", + Igor => "igor", + Esmeralda => "esmeralda", + LocalNet => "localnet", + } + } +} + +impl TryFrom for Network { + type Error = (); + + fn try_from(v: u8) -> Result { + match v { + x if x == Network::MainNet as u8 => Ok(Network::MainNet), + x if x == Network::StageNet as u8 => Ok(Network::StageNet), + x if x == Network::NextNet as u8 => Ok(Network::NextNet), + x if x == Network::LocalNet as u8 => Ok(Network::LocalNet), + x if x == Network::Igor as u8 => Ok(Network::Igor), + x if x == Network::Esmeralda as u8 => Ok(Network::Esmeralda), + _ => Err(()), + } + } +} + +impl Default for Network { + #[cfg(tari_target_network_mainnet)] + fn default() -> Self { + Network::StageNet + } + + #[cfg(tari_target_network_nextnet)] + fn default() -> Self { + Network::NextNet + } + + #[cfg(not(any(tari_target_network_mainnet, tari_target_network_nextnet)))] + fn default() -> Self { + Network::Esmeralda + } +} diff --git a/applications/minotari_ledger_wallet/common/src/utils.rs b/applications/minotari_ledger_wallet/common/src/utils.rs index 935a4358c85..de4ce31cd06 100644 --- a/applications/minotari_ledger_wallet/common/src/utils.rs +++ b/applications/minotari_ledger_wallet/common/src/utils.rs @@ -1,27 +1,15 @@ // Copyright 2024 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 alloc::string::{String, ToString}; +// SPDX-License-Identifier: BSD-3-Clause +use alloc::{ + borrow::ToOwned, + string::{String, ToString}, + vec::Vec, +}; + +pub const PUSH_PUBKEY_IDENTIFIER: &str = "217e"; + +/// Convert a u16 to a string pub fn u16_to_string(number: u16) -> String { let mut buffer = [0u8; 6]; // Maximum length for a 16-bit integer (including null terminator) let mut pos = 0; @@ -50,3 +38,23 @@ pub fn u16_to_string(number: u16) -> String { String::from_utf8_lossy(&buffer[..pos]).to_string() } + +/// Convert a hex string to serialized bytes made up as an identifier concatenated with data +pub fn hex_to_bytes_serialized(identifier: &str, data: &str) -> Result, String> { + if identifier.len() % 2 != 0 { + return Err("Invalid identifier".to_string()); + } + if data.len() % 2 != 0 { + return Err("Invalid payload".to_string()); + } + + let hex = identifier.to_owned() + data; + let hex = hex.as_str(); + + let mut serialized = Vec::new(); + for i in 0..hex.len() / 2 { + let byte = u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16).map_err(|_e| "Invalid hex string".to_string())?; + serialized.push(byte); + } + Ok(serialized) +} diff --git a/applications/minotari_ledger_wallet/comms/Cargo.toml b/applications/minotari_ledger_wallet/comms/Cargo.toml index 97a025d5728..61d57b7c34d 100644 --- a/applications/minotari_ledger_wallet/comms/Cargo.toml +++ b/applications/minotari_ledger_wallet/comms/Cargo.toml @@ -23,3 +23,6 @@ thiserror = "1.0.26" rand = "0.8" once_cell = "1.19.0" log = "0.4.20" + +[dev-dependencies] +borsh = "1.2" diff --git a/applications/minotari_ledger_wallet/comms/src/lib.rs b/applications/minotari_ledger_wallet/comms/src/lib.rs index d9c242ccc9f..a5c1bef4ced 100644 --- a/applications/minotari_ledger_wallet/comms/src/lib.rs +++ b/applications/minotari_ledger_wallet/comms/src/lib.rs @@ -23,3 +23,66 @@ pub mod accessor_methods; pub mod error; pub mod ledger_wallet; + +#[cfg(test)] +mod test { + use borsh::BorshSerialize; + use minotari_ledger_wallet_common::{hex_to_bytes_serialized, PUSH_PUBKEY_IDENTIFIER}; + use rand::rngs::OsRng; + use tari_crypto::{ + keys::{PublicKey, SecretKey}, + ristretto::{RistrettoPublicKey, RistrettoSecretKey}, + }; + use tari_script::{script, slice_to_boxed_message}; + use tari_utilities::{hex::Hex, ByteArray}; + + const NOP_IDENTIFIER: &str = "0173"; + const PUSH_ONE_IDENTIFIER: &str = "017c"; + const CHECK_SIG_VERIFY_IDENTIFIER: &str = "21ad"; + + #[test] + // This is testing the serialization of the 'PushPubKey' script and the byte representation of the script as needed + // for native serialization in the tari ledger wallet code. Other script types where the exact hex representation of + // the script payload could easily be determined are tested in the same way to verify the concept. + // This test should highlight if any changes are made to the script serialization. Primary script: + // - 'script!(PushPubKey(Box::new()))' + // and additional ones used for testing: + // - 'script!(Nop)' + // - 'script!(PushOne)' + // - `CheckSigVerify())` + fn test_push_pub_key_serialized_byte_representation() { + let mut scripts = Vec::new(); + + scripts.push((script!(Nop), NOP_IDENTIFIER, "".to_string())); + scripts.push((script!(PushOne), PUSH_ONE_IDENTIFIER, "".to_string())); + + for pub_key in [ + RistrettoPublicKey::default(), + RistrettoPublicKey::from_secret_key(&RistrettoSecretKey::random(&mut OsRng)), + ] { + scripts.push(( + script!(PushPubKey(Box::new(pub_key.clone()))), + PUSH_PUBKEY_IDENTIFIER, + pub_key.to_hex(), + )); + } + + let key = RistrettoSecretKey::random(&mut OsRng); + let msg = slice_to_boxed_message(key.as_bytes()); + scripts.push((script!(CheckSigVerify(msg)), CHECK_SIG_VERIFY_IDENTIFIER, key.to_hex())); + + for (script, hex_identifier, hex_payload) in scripts { + let mut serialized = Vec::new(); + script.serialize(&mut serialized).unwrap(); + let hex_data = hex_identifier.to_owned() + &hex_payload; + assert_eq!(hex_data, serialized.to_vec().to_hex()); + assert_eq!( + hex_to_bytes_serialized(hex_identifier, &hex_payload).unwrap(), + serialized.as_slice(), + "Change in script serialization detected: {:?}, expected {}", + script, + hex_identifier + ); + } + } +} diff --git a/common/src/configuration/network.rs b/common/src/configuration/network.rs index 5c40470fd1b..24172ee83fa 100644 --- a/common/src/configuration/network.rs +++ b/common/src/configuration/network.rs @@ -126,6 +126,7 @@ impl FromStr for Network { } } } + impl TryFrom for Network { type Error = ConfigurationError; diff --git a/infrastructure/tari_script/Cargo.toml b/infrastructure/tari_script/Cargo.toml index c2aed521a15..c74d23cc25e 100644 --- a/infrastructure/tari_script/Cargo.toml +++ b/infrastructure/tari_script/Cargo.toml @@ -25,3 +25,4 @@ thiserror = "1.0.30" [dev-dependencies] rand = "0.8" +hex = "0.4" \ No newline at end of file