diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da625db33..994a48cd4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,7 +38,6 @@ set(DBB-FIRMWARE-SOURCES ${CMAKE_SOURCE_DIR}/src/workflow/blocking.c ${CMAKE_SOURCE_DIR}/src/workflow/idle_workflow.c ${CMAKE_SOURCE_DIR}/src/workflow/orientation_screen.c - ${CMAKE_SOURCE_DIR}/src/apps/btc/btc_common.c ${CMAKE_SOURCE_DIR}/src/queue.c ${CMAKE_SOURCE_DIR}/src/usb/usb_processing.c ) @@ -389,8 +388,6 @@ add_custom_target(rust-bindgen --rustified-enum simple_type_t --rustified-enum multisig_script_type_t --rustified-enum output_type_t - --allowlist-function btc_common_pkscript_from_payload - --allowlist-function btc_common_pkscript_from_multisig --allowlist-var MAX_VARINT_SIZE --allowlist-var MAX_PK_SCRIPT_SIZE --allowlist-function reboot diff --git a/src/apps/btc/btc_common.c b/src/apps/btc/btc_common.c deleted file mode 100644 index ce3e638ae..000000000 --- a/src/apps/btc/btc_common.c +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019 Shift Cryptosecurity AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include "btc_common.h" - -#include -#include -#include -#include -#include -#include - -bool btc_common_pkscript_from_multisig( - const multisig_t* multisig, - uint32_t keypath_change, - uint32_t keypath_address, - uint8_t* script_out, - size_t* script_out_size) -{ - uint8_t pubkeys[MULTISIG_P2WSH_MAX_SIGNERS * EC_PUBLIC_KEY_LEN]; - - for (size_t index = 0; index < multisig->xpubs_count; index++) { - struct ext_key xpub = {0}; - if (bip32_key_unserialize(multisig->xpubs[index], sizeof(multisig->xpubs[index]), &xpub) != - WALLY_OK) { - return false; - } - struct ext_key derived_cosigner_xpub = {0}; - const uint32_t keypath[2] = {keypath_change, keypath_address}; - if (bip32_key_from_parent_path( - &xpub, keypath, 2, BIP32_FLAG_KEY_PUBLIC, &derived_cosigner_xpub) != WALLY_OK) { - return false; - } - memcpy( - &pubkeys[index * EC_PUBLIC_KEY_LEN], derived_cosigner_xpub.pub_key, EC_PUBLIC_KEY_LEN); - } - - size_t written; - if (wally_scriptpubkey_multisig_from_bytes( - pubkeys, - multisig->xpubs_count * EC_PUBLIC_KEY_LEN, - multisig->threshold, - WALLY_SCRIPT_MULTISIG_SORTED, - script_out, - *script_out_size, - &written) != WALLY_OK) { - return false; - } - if (written > *script_out_size) { - // Double check since the function above sets written to script_len if the buffer was too - // short. - return false; - } - *script_out_size = written; - - return true; -} diff --git a/src/apps/btc/btc_common.h b/src/apps/btc/btc_common.h deleted file mode 100644 index e814b6f54..000000000 --- a/src/apps/btc/btc_common.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2019 Shift Cryptosecurity AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _APPS_BTC_COMMON_H -#define _APPS_BTC_COMMON_H - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#define MULTISIG_P2WSH_MAX_SIGNERS 15 - -typedef struct { - size_t xpubs_count; - uint8_t xpubs[MULTISIG_P2WSH_MAX_SIGNERS][BIP32_SERIALIZED_LEN]; - uint32_t threshold; -} multisig_t; - -// see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer -#define MAX_VARINT_SIZE (9) -// current expected max pk script size is a m-of-15 multisig. 700 is also enough for m-of-20, which -// is technically possible to extend to if needed. -#define MAX_PK_SCRIPT_SIZE (700) - -/** - * Creates a n-of-m multisig script based on OP_CHECKMULTISIG. 0 Result { - Ok(bitbox02::app_btc::Multisig { - xpubs_count: multisig.xpubs.len() as _, - xpubs: { - let mut xpubs = [[0u8; 78]; MAX_SIGNERS]; - for (i, xpub) in multisig.xpubs.iter().enumerate() { - xpubs[i] = bip32::Xpub::from(xpub) - .serialize(Some(bip32::XPubType::Xpub)) - .or(Err(Error::InvalidInput))? - .try_into() - .or(Err(Error::Generic))?; - } - xpubs - }, - threshold: multisig.threshold, - }) -} - pub enum SortXpubs { No, Yes, @@ -302,6 +283,46 @@ pub fn validate(multisig: &Multisig, keypath: &[u32], expected_coin: u32) -> Res Ok(()) } +/// Creates a n-of-m multisig script based on OP_CHECKMULTISIG. 0 Result, Error> { + if multisig.xpubs.len() < 2 || multisig.xpubs.len() > MAX_SIGNERS { + return Err(Error::InvalidInput); + } + if multisig.threshold == 0 || multisig.threshold > multisig.xpubs.len() as _ { + return Err(Error::InvalidInput); + } + let mut pubkeys: Vec> = multisig + .xpubs + .iter() + .map(|xpub| -> Result, ()> { + Ok(bip32::Xpub::from(xpub) + .derive(&[keypath_change, keypath_address])? + .public_key() + .to_vec()) + }) + .collect::>()?; + pubkeys.sort(); + + let mut script_builder = bitcoin::script::Builder::new().push_int(multisig.threshold as _); + for pk in pubkeys.iter() { + let pk: &bitcoin::script::PushBytes = + pk.as_slice().try_into().map_err(|_| Error::Generic)?; + script_builder = script_builder.push_slice(pk); + } + script_builder = script_builder + .push_int(pubkeys.len() as _) + .push_opcode(bitcoin::opcodes::all::OP_CHECKMULTISIG); + + Ok(script_builder.into_bytes()) +} + #[cfg(test)] mod tests { use super::*; @@ -684,4 +705,165 @@ mod tests { assert!(validate(&invalid, keypath, expected_coin).is_err()); } } + + #[test] + fn test_pkscript() { + struct Test<'a> { + threshold: u32, + xpubs: &'a [&'a str], + keypath_change: u32, + keypath_address: u32, + expected_script_hex: &'a str, + } + + let tests = [ + Test { + threshold: 1, + xpubs: &[ + "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", + "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", + ], + keypath_change: 0, + keypath_address: 1, + expected_script_hex: "51210217fb1e3415108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a612102ae0826124c98c4e255c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d3565052ae", + }, + // different xpub order should have the same result. + Test { + threshold: 1, + xpubs: &[ + "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", + "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", + ], + keypath_change: 0, + keypath_address: 1, + expected_script_hex: "51210217fb1e3415108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a612102ae0826124c98c4e255c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d3565052ae", + }, + Test { + threshold: 1, + xpubs: &[ + "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", + "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", + ], + keypath_change: 1, + keypath_address: 10, + expected_script_hex: "512102b6da3d9e33c3bcee679ef3bb2fca8e60c4a8ade06519146c77b007778756b2c92103f42b45d0d91039df309ff5d10d0a044fb4eb6595d015281be2d56c288524d68f52ae", + }, + Test { + threshold: 2, + xpubs: &[ + "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", + "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", + ], + keypath_change: 0, + keypath_address: 1, + expected_script_hex: "52210217fb1e3415108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a612102ae0826124c98c4e255c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d3565052ae", + }, + Test { + threshold: 15, + xpubs: &[ + "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", + "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", + "xpub6E9Qk6G1PAZPqheZ85sySQc9fxS8mp2muF9dNaXpnCGvW2NB13rCm4TKLo9vJaCyxcXBJPF2yBSkKuivLGA5fxuXhbRSL2Sp8HfgxEMFYD3", + "xpub6DxHJ5evyWcSBrG9zCauY1zrh3J6HkiBGLzgG4wvuRaDQYxF6suuPNh1hD2VktphRhEwWXECaWLXo1PkVkGn7hW6vq6AN3ZgqFUrQ7boHqs", + "xpub6EdCXJqHFRVqVCZpain6TMzkpmcU6pLU5jSzjUUouumdkzKUAmvBiTsVeJSwxdBzH5mLU1FEFka7jsrs1JeRbqJnwHE31bVF26gkJQ5SCs3", + "xpub6EG6LDy2hGg7NBUKyPzqe8k57Jm6H9WmH85MKKWGVTCbr5tVDt8oaKSAArXga4LbYy6Aawfzr324kXq4ia4vSkRBzPCktDv5XJbPRg3sXsz", + "xpub6EVoeT8mm6jfq5mtG3Kuv2ozffH1oRaLYsq88N1x7225QBzfBeZxbdx6sGYpFpkcJohzLHXhM7GjqqyrvxzkfvZjydSCGPbaDxWirKH3TRp", + "xpub6FNtqhDqFmHJxZsocfd2LftXzZAcDXK2ijhzcscsrsu46Ccz3uv7rrZYbFEvA98svjzkD49x8K2Mi2BuJuhyZHfTtBfdgeUc66JdCez8KG8", + "xpub6F1behqQRigaf5gbFbbdjrNV4M64UTQTrzEU535dURgBMJakSFpiZkXveqEscL6Y6gyveFwxp8PGKn3q9MLtwk1UmyRRkFCQb2X6hfvGYWt", + "xpub6FG3mVwCkRmtmFuCKZa6MXc4kCPEd5bKrjrNAPgwcmekysnsHBaadhuzo2jV2AjYyg4QjGmu3LgyEUAw4bUXPUsQJG61ZtKM7MVkBxbxcVj", + "xpub6DoEJEeUNBkLF7zmKKu8YewqK1PcXWfuek2J2Y8USdGh2McQStsGbVn2oqv521KdJiESeRW4mBBtpBamKHNaD6yZhAbyPwy51VyqHS4EFq6", + "xpub6EzUjWSuWk7kBKZTKsdXkFMUropKFLq1iWabRtQpXckxf6s9NMR8UrmY6aYQUuvHyXpYo78RJhyZ1sK9Re4ZbdzpG4Awm6yW221N2AQM6ZU", + "xpub6DeznbrZVRaZ4P5Xr79JBs8dNyBMamFmAgAX52o73Pap5RLkMmUi9oQH1sopigbSr6gwUoDMd3EhpoB5tBZXzu4HWJiGETKQGneYtRpjaJB", + "xpub6EYf1KXzjaTgcNZFq7pVXGtGDkqHFPvEGBDygkDodz94ZpDazWppGe57hDhTA94z6zeGEubqyLqUMP67ubdd8hf6BbKYA9qtdDf3yM5wdJX", + "xpub6ELR9CAGqxwbKcCh591AfKs74neEY9UjtNbvLjrpsxH2FakqE238J1DmsFHePtXXyYhkZshW3qTWWwhENTQgWb6KHaf7SQnVovsKxtvZQaG", + ], + keypath_change: 0, + keypath_address: 1, + expected_script_hex: "5f210210e4a9e6d84a7d4b88d5f0450ade30de2046f824374f9b4954a6f03bd37b7269210217fb1e341\ + 5108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a61210219ad58aa89a3e1669b0757b7\ + b87d72350cd94675421365a9b7ae781fabeb04ec210230a8551d874b4a3633195c1ba80d0fd5d4e6cf7\ + 917b07f00379893490f795fbe210242f82d15933cf3487567405699910eae5c4b5b24821eeaceeac0ea\ + da231a760421024be1e5f4fd6c4248b05df752d19754aad4ca663f62f20fd7ac54616899870ebc21024\ + d5cae14247c53ec7943a78ddb016a939e98756526587ec4bb72789334e698292102ae0826124c98c4e2\ + 55c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d356502102cd014c5921c2f40c0b8de3cf32f9b67\ + 89737e2a06677c4da7325623bcb0af89421033f63c02d09195b9c7efb7b75e18da8b768b5c3e0517082\ + 98d6580634284c28122103410a5da3477482eea7be703bd81d00d4498b7babfbd25f7c930a137a5025c\ + 0b721035b0322eeec4356d59edf4b6213cf78409c6f2e05c26e65b04c503f98a38ec78b21037ff295f8\ + 45fabf9eb4ada869bfa62bde1ede38f074b12bf12a2a2f214282cef82103aef77f1780440ba2445aef6\ + d3ecf5d0b8dae3b6f22abc44734e1d4c257dc631f2103cd01c7cd59d6956bf07f1e7acba7c41a126ba5\ + 49c07d0c88988c94846ecd88005fae", + }, + ]; + + for test in tests { + assert_eq!( + hex::encode( + pkscript( + &Multisig { + threshold: test.threshold, + xpubs: test + .xpubs + .iter() + .map(|xpub| parse_xpub(xpub).unwrap()) + .collect(), + our_xpub_index: 0, + script_type: ScriptType::P2wsh as _ + }, + test.keypath_change, + test.keypath_address + ) + .unwrap() + ) + .as_str(), + test.expected_script_hex + ); + } + } + + #[test] + fn test_pkscript_unhappy() { + struct Test<'a> { + threshold: u32, + xpubs: &'a [&'a str], + } + + let tests = [ + Test { + threshold: 1, + xpubs: &[], + }, + Test { + threshold: 0, + xpubs: &[ + "xpub6EMfjyGVUvwhpc3WKN1zXhMFGKJGMaSBPqbja4tbGoYvRBSXeTBCaqrRDjcuGTcaY95JrrAnQvDG3pdQPdtnYUCugjeksHSbyZT7rq38VQF", + "xpub6ERxBysTYfQyY4USv6c6J1HNVv9hpZFN9LHVPu47Ac4rK8fLy6NnAeeAHyEsMvG4G66ay5aFZii2VM7wT3KxLKX8Q8keZPd67kRGmrD1WJj", + ], + }, + Test { + threshold: 3, + xpubs: &[ + "xpub6EMfjyGVUvwhpc3WKN1zXhMFGKJGMaSBPqbja4tbGoYvRBSXeTBCaqrRDjcuGTcaY95JrrAnQvDG3pdQPdtnYUCugjeksHSbyZT7rq38VQF", + "xpub6ERxBysTYfQyY4USv6c6J1HNVv9hpZFN9LHVPu47Ac4rK8fLy6NnAeeAHyEsMvG4G66ay5aFZii2VM7wT3KxLKX8Q8keZPd67kRGmrD1WJj", + ], + }, + ]; + + for test in tests { + assert!(pkscript( + &Multisig { + threshold: test.threshold, + xpubs: test + .xpubs + .iter() + .map(|xpub| parse_xpub(xpub).unwrap()) + .collect(), + our_xpub_index: 0, + script_type: ScriptType::P2wsh as _ + }, + 1, + 2, + ) + .is_err()); + } + } } diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs index f4f7afad8..bb77e3406 100644 --- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs +++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs @@ -293,8 +293,8 @@ fn sighash_script( config: Some(pb::btc_script_config::Config::Multisig(multisig)), }), .. - } => Ok(bitbox02::app_btc::pkscript_from_multisig( - &super::multisig::convert_multisig(multisig)?, + } => Ok(super::multisig::pkscript( + multisig, keypath[keypath.len() - 2], keypath[keypath.len() - 1], )?), diff --git a/src/rust/bitbox02-sys/wrapper.h b/src/rust/bitbox02-sys/wrapper.h index 02fb1c790..dda3edfcf 100644 --- a/src/rust/bitbox02-sys/wrapper.h +++ b/src/rust/bitbox02-sys/wrapper.h @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include #include #include diff --git a/src/rust/bitbox02/src/app_btc.rs b/src/rust/bitbox02/src/app_btc.rs deleted file mode 100644 index e6cf53ad2..000000000 --- a/src/rust/bitbox02/src/app_btc.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Shift Crypto AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -extern crate alloc; -use alloc::vec::Vec; - -pub use bitbox02_sys::multisig_t as Multisig; - -pub fn pkscript_from_multisig( - multisig: &Multisig, - keypath_change: u32, - keypath_address: u32, -) -> Result, ()> { - let mut out = [0u8; bitbox02_sys::MAX_PK_SCRIPT_SIZE as usize]; - let mut out_len: usize = out.len() as _; - match unsafe { - bitbox02_sys::btc_common_pkscript_from_multisig( - multisig, - keypath_change, - keypath_address, - out.as_mut_ptr(), - &mut out_len, - ) - } { - true => Ok(out[..out_len].to_vec()), - false => Err(()), - } -} diff --git a/src/rust/bitbox02/src/lib.rs b/src/rust/bitbox02/src/lib.rs index 6259f5998..c05903549 100644 --- a/src/rust/bitbox02/src/lib.rs +++ b/src/rust/bitbox02/src/lib.rs @@ -30,8 +30,6 @@ extern crate lazy_static; #[cfg(feature = "testing")] pub mod testing; -#[cfg(any(feature = "app-bitcoin", feature = "app-litecoin"))] -pub mod app_btc; #[cfg(feature = "app-ethereum")] pub mod app_eth; pub mod bip32; diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index 874dd164d..8f79f0516 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -220,8 +220,6 @@ set(TEST_LIST "" random "-Wl,--wrap=rand,--wrap=wally_sha256" - app_btc_common - "" ui_components "" ui_util diff --git a/test/unit-test/test_app_btc_common.c b/test/unit-test/test_app_btc_common.c deleted file mode 100644 index e304f7067..000000000 --- a/test/unit-test/test_app_btc_common.c +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2019 Shift Cryptosecurity AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -typedef struct { - uint32_t threshold; - size_t xpubs_count; - const char* xpubs[15]; - uint32_t keypath_change; - uint32_t keypath_address; - const char* expected_script_hex; -} test_case_redeemscript_multisig_p2wsh; - -static void _test_btc_common_pkscript_from_multisig(void** state) -{ - // clang-format off - const test_case_redeemscript_multisig_p2wsh tests[] = { - { - .threshold = 1, - .xpubs_count = 2, - .xpubs = - { - "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", - "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", - }, - .keypath_change = 0, - .keypath_address = 1, - .expected_script_hex = - "51210217fb1e3415108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a612102ae082612" - "4c98c4e255c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d3565052ae", - }, - { // different xpub order should have the same result. - .threshold = 1, - .xpubs_count = 2, - .xpubs = - { - "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", - "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", - }, - .keypath_change = 0, - .keypath_address = 1, - .expected_script_hex = - "51210217fb1e3415108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a612102ae082612" - "4c98c4e255c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d3565052ae", - }, - { - .threshold = 1, - .xpubs_count = 2, - .xpubs = - { - "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", - "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", - }, - .keypath_change = 1, - .keypath_address = 10, - .expected_script_hex = - "512102b6da3d9e33c3bcee679ef3bb2fca8e60c4a8ade06519146c77b007778756b2c92103f42b45d0d" - "91039df309ff5d10d0a044fb4eb6595d015281be2d56c288524d68f52ae" - }, - { - .threshold = 2, - .xpubs_count = 2, - .xpubs = - { - "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", - "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", - }, - .keypath_change = 0, - .keypath_address = 1, - .expected_script_hex = - "52210217fb1e3415108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a612102ae082612" - "4c98c4e255c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d3565052ae", - }, - { - .threshold = 15, - .xpubs_count = 15, - .xpubs = - { - "xpub6FEZ9Bv73h1vnE4TJG4QFj2RPXJhhsPbnXgFyH3ErLvpcZrDcynY65bhWga8PazWHLSLi23PoBhGcLcYW6JRiJ12zXZ9Aop4LbAqsS3gtcy", - "xpub6EGAio99SxruuNxoBtG4fbYx3xM8fs7wjYJLRNcUg7UQin3LTANQiUYyb3RLjZ2EAyLsQBrtbNENUGh3oWzjHtgfQ3mtjPNFgNMronzTTVR", - "xpub6E9Qk6G1PAZPqheZ85sySQc9fxS8mp2muF9dNaXpnCGvW2NB13rCm4TKLo9vJaCyxcXBJPF2yBSkKuivLGA5fxuXhbRSL2Sp8HfgxEMFYD3", - "xpub6DxHJ5evyWcSBrG9zCauY1zrh3J6HkiBGLzgG4wvuRaDQYxF6suuPNh1hD2VktphRhEwWXECaWLXo1PkVkGn7hW6vq6AN3ZgqFUrQ7boHqs", - "xpub6EdCXJqHFRVqVCZpain6TMzkpmcU6pLU5jSzjUUouumdkzKUAmvBiTsVeJSwxdBzH5mLU1FEFka7jsrs1JeRbqJnwHE31bVF26gkJQ5SCs3", - "xpub6EG6LDy2hGg7NBUKyPzqe8k57Jm6H9WmH85MKKWGVTCbr5tVDt8oaKSAArXga4LbYy6Aawfzr324kXq4ia4vSkRBzPCktDv5XJbPRg3sXsz", - "xpub6EVoeT8mm6jfq5mtG3Kuv2ozffH1oRaLYsq88N1x7225QBzfBeZxbdx6sGYpFpkcJohzLHXhM7GjqqyrvxzkfvZjydSCGPbaDxWirKH3TRp", - "xpub6FNtqhDqFmHJxZsocfd2LftXzZAcDXK2ijhzcscsrsu46Ccz3uv7rrZYbFEvA98svjzkD49x8K2Mi2BuJuhyZHfTtBfdgeUc66JdCez8KG8", - "xpub6F1behqQRigaf5gbFbbdjrNV4M64UTQTrzEU535dURgBMJakSFpiZkXveqEscL6Y6gyveFwxp8PGKn3q9MLtwk1UmyRRkFCQb2X6hfvGYWt", - "xpub6FG3mVwCkRmtmFuCKZa6MXc4kCPEd5bKrjrNAPgwcmekysnsHBaadhuzo2jV2AjYyg4QjGmu3LgyEUAw4bUXPUsQJG61ZtKM7MVkBxbxcVj", - "xpub6DoEJEeUNBkLF7zmKKu8YewqK1PcXWfuek2J2Y8USdGh2McQStsGbVn2oqv521KdJiESeRW4mBBtpBamKHNaD6yZhAbyPwy51VyqHS4EFq6", - "xpub6EzUjWSuWk7kBKZTKsdXkFMUropKFLq1iWabRtQpXckxf6s9NMR8UrmY6aYQUuvHyXpYo78RJhyZ1sK9Re4ZbdzpG4Awm6yW221N2AQM6ZU", - "xpub6DeznbrZVRaZ4P5Xr79JBs8dNyBMamFmAgAX52o73Pap5RLkMmUi9oQH1sopigbSr6gwUoDMd3EhpoB5tBZXzu4HWJiGETKQGneYtRpjaJB", - "xpub6EYf1KXzjaTgcNZFq7pVXGtGDkqHFPvEGBDygkDodz94ZpDazWppGe57hDhTA94z6zeGEubqyLqUMP67ubdd8hf6BbKYA9qtdDf3yM5wdJX", - "xpub6ELR9CAGqxwbKcCh591AfKs74neEY9UjtNbvLjrpsxH2FakqE238J1DmsFHePtXXyYhkZshW3qTWWwhENTQgWb6KHaf7SQnVovsKxtvZQaG", - }, - .keypath_change = 0, - .keypath_address = 1, - .expected_script_hex = - "5f210210e4a9e6d84a7d4b88d5f0450ade30de2046f824374f9b4954a6f03bd37b7269210217fb1e341" - "5108fee2b004c932dc5a89eabf3587e3e7b21165c123de1f37a3a61210219ad58aa89a3e1669b0757b7" - "b87d72350cd94675421365a9b7ae781fabeb04ec210230a8551d874b4a3633195c1ba80d0fd5d4e6cf7" - "917b07f00379893490f795fbe210242f82d15933cf3487567405699910eae5c4b5b24821eeaceeac0ea" - "da231a760421024be1e5f4fd6c4248b05df752d19754aad4ca663f62f20fd7ac54616899870ebc21024" - "d5cae14247c53ec7943a78ddb016a939e98756526587ec4bb72789334e698292102ae0826124c98c4e2" - "55c1a6cc404ff6d2448a0d9f853e6d72d6b02d9ad2d356502102cd014c5921c2f40c0b8de3cf32f9b67" - "89737e2a06677c4da7325623bcb0af89421033f63c02d09195b9c7efb7b75e18da8b768b5c3e0517082" - "98d6580634284c28122103410a5da3477482eea7be703bd81d00d4498b7babfbd25f7c930a137a5025c" - "0b721035b0322eeec4356d59edf4b6213cf78409c6f2e05c26e65b04c503f98a38ec78b21037ff295f8" - "45fabf9eb4ada869bfa62bde1ede38f074b12bf12a2a2f214282cef82103aef77f1780440ba2445aef6" - "d3ecf5d0b8dae3b6f22abc44734e1d4c257dc631f2103cd01c7cd59d6956bf07f1e7acba7c41a126ba5" - "49c07d0c88988c94846ecd88005fae", - }, - }; - // clang-format on - - for (size_t test_case_index = 0; - test_case_index < sizeof(tests) / sizeof(test_case_redeemscript_multisig_p2wsh); - test_case_index++) { - const test_case_redeemscript_multisig_p2wsh* test_case = &tests[test_case_index]; - multisig_t multisig = { - .threshold = test_case->threshold, - .xpubs_count = test_case->xpubs_count, - }; - for (size_t xpub_idx = 0; xpub_idx < test_case->xpubs_count; xpub_idx++) { - size_t written; - uint8_t deser[BIP32_SERIALIZED_LEN + BASE58_CHECKSUM_LEN]; - assert_int_equal( - wally_base58_to_bytes( - test_case->xpubs[xpub_idx], - BASE58_FLAG_CHECKSUM, - deser, - sizeof(deser), - &written), - WALLY_OK); - memcpy(multisig.xpubs[xpub_idx], deser, sizeof(multisig.xpubs[xpub_idx])); - } - - uint8_t script[520]; - size_t script_size = sizeof(script); - assert_true(btc_common_pkscript_from_multisig( - &multisig, - test_case->keypath_change, - test_case->keypath_address, - script, - &script_size)); - assert_true(script_size <= sizeof(script)); - - char script_hex[2 * script_size + 1]; - util_uint8_to_hex(script, script_size, script_hex); - assert_string_equal(script_hex, test_case->expected_script_hex); - } -} - -static void _test_btc_common_pkscript_from_multisig_unhappy(void** state) -{ - multisig_t multisig = { - .threshold = 1, - .xpubs_count = 2, - }; - uint8_t deser[BIP32_SERIALIZED_LEN + BASE58_CHECKSUM_LEN]; - size_t written; - assert_int_equal( - wally_base58_to_bytes( - "xpub6EMfjyGVUvwhpc3WKN1zXhMFGKJGMaSBPqbja4tbGoYvRBSXeTBCaqrRDjcuGTcaY95JrrAnQvDG3pdQPd" - "tnYUCugjeksHSbyZT7rq38VQF", - BASE58_FLAG_CHECKSUM, - deser, - sizeof(deser), - &written), - WALLY_OK); - memcpy(multisig.xpubs[0], deser, sizeof(multisig.xpubs[0])); - assert_int_equal( - wally_base58_to_bytes( - "xpub6ERxBysTYfQyY4USv6c6J1HNVv9hpZFN9LHVPu47Ac4rK8fLy6NnAeeAHyEsMvG4G66ay5aFZii2VM7wT3" - "KxLKX8Q8keZPd67kRGmrD1WJj", - BASE58_FLAG_CHECKSUM, - deser, - sizeof(deser), - &written), - WALLY_OK); - memcpy(multisig.xpubs[1], deser, sizeof(multisig.xpubs[1])); - uint8_t script[520]; - size_t script_size; - - multisig_t invalid = multisig; - invalid.xpubs_count = 0; - script_size = sizeof(script); - assert_false(btc_common_pkscript_from_multisig(&invalid, 1, 2, script, &script_size)); - - invalid = multisig; - invalid.threshold = 0; - script_size = sizeof(script); - assert_false(btc_common_pkscript_from_multisig(&invalid, 1, 2, script, &script_size)); - - invalid = multisig; - invalid.threshold = multisig.xpubs_count + 1; - script_size = sizeof(script); - assert_false(btc_common_pkscript_from_multisig(&invalid, 1, 2, script, &script_size)); - - invalid = multisig; - script_size = 0; - assert_false(btc_common_pkscript_from_multisig(&invalid, 1, 2, script, &script_size)); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(_test_btc_common_pkscript_from_multisig), - cmocka_unit_test(_test_btc_common_pkscript_from_multisig_unhappy), - }; - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/unit-test/test_keystore_functional.c b/test/unit-test/test_keystore_functional.c index 993a83403..9de48edc4 100644 --- a/test/unit-test/test_keystore_functional.c +++ b/test/unit-test/test_keystore_functional.c @@ -19,7 +19,6 @@ #include -#include #include #include #include