diff --git a/doc/API.md b/doc/API.md index b0fb5042..00a6be8a 100644 --- a/doc/API.md +++ b/doc/API.md @@ -62,7 +62,7 @@ Display general information about the current daemon state. | `vaults` | integer | Current number of vaults (unconfirmed are included) | | `managers_threshold` | integer | Number of managers needed for spending the `unvault_tx` | | `descriptors` | object | Three `string` entries: `deposit`, `unvault` and `cpfp` for the three Miniscript descriptors | - +| `participant_type` | string | Answer can be `stakeholder`, `manager`, `stakeholdermanager` | ### `getdepositaddress` diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 5807a6f3..31d9cd8c 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -8,7 +8,7 @@ mod utils; pub use crate::{ bitcoind::{interface::WalletTransaction, BitcoindError}, communication::ServerStatus, - revaultd::{BlockchainTip, VaultStatus}, + revaultd::{BlockchainTip, UserRole, VaultStatus}, }; use crate::{ communication::{ @@ -268,6 +268,15 @@ impl DaemonControl { }) .count(); + assert!(revaultd.is_stakeholder() || revaultd.is_manager()); + let participant_type = if revaultd.is_manager() && revaultd.is_stakeholder() { + UserRole::StakeholderManager + } else if revaultd.is_manager() { + UserRole::Manager + } else { + UserRole::Stakeholder + }; + GetInfoResult { version: VERSION.to_string(), network: revaultd.bitcoind_config.network, @@ -280,6 +289,7 @@ impl DaemonControl { unvault: revaultd.unvault_descriptor.clone(), cpfp: revaultd.cpfp_descriptor.clone(), }, + participant_type, } } @@ -1430,6 +1440,8 @@ pub struct GetInfoResult { pub vaults: usize, pub managers_threshold: usize, pub descriptors: GetInfoDescriptors, + #[serde(serialize_with = "ser_to_string", deserialize_with = "deser_from_str")] + pub participant_type: UserRole, } /// Information about a vault. diff --git a/src/commands/utils.rs b/src/commands/utils.rs index 97255649..5ab3bc4f 100644 --- a/src/commands/utils.rs +++ b/src/commands/utils.rs @@ -495,11 +495,9 @@ mod tests { }, schema::{DbTransaction, DbVault}, }, - revaultd::{RevaultD, VaultStatus}, + revaultd::{RevaultD, UserRole, VaultStatus}, setup_db, - utils::test_utils::{ - dummy_revaultd, insert_vault_in_db, test_datadir, MockBitcoindThread, UserRole, - }, + utils::test_utils::{dummy_revaultd, insert_vault_in_db, test_datadir, MockBitcoindThread}, }; use revault_tx::{ bitcoin::{ @@ -888,7 +886,7 @@ mod tests { #[test] fn test_listvaults_from_db() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); setup_db(&mut revaultd).unwrap(); let vaults = create_vaults(&revaultd); @@ -978,7 +976,7 @@ mod tests { #[test] fn test_vaults_from_deposits() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_file = revaultd.db_file(); setup_db(&mut revaultd).unwrap(); let vaults = create_vaults(&revaultd); @@ -1390,7 +1388,7 @@ mod tests { #[test] fn test_gethistory() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); setup_db(&mut revaultd).unwrap(); let db_file = revaultd.db_file(); diff --git a/src/communication.rs b/src/communication.rs index 8100dd2a..38ddb4a6 100644 --- a/src/communication.rs +++ b/src/communication.rs @@ -391,13 +391,14 @@ pub fn check_spend_transaction_size(revaultd: &RevaultD, spend_tx: SpendTransact #[cfg(test)] mod tests { + use crate::revaultd::UserRole; use crate::{ communication::*, database::{ bitcointx::{RevaultTx, TransactionType}, schema::DbTransaction, }, - utils::test_utils::{dummy_revaultd, test_datadir, UserRole}, + utils::test_utils::{dummy_revaultd, test_datadir}, }; use revault_net::{ message, sodiumoxide::crypto::box_::curve25519xsalsa20poly1305::gen_keypair, @@ -1205,7 +1206,7 @@ mod tests { #[test] fn test_check_spend_transaction_size() { let datadir = test_datadir(); - let revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); // 3 inputs, 4 outputs, 3 stakeholders and 3 manager psbt. No problem. let tx = SpendTransaction::from_psbt_str("cHNidP8BAP0ZAQIAAAADSe9QbkOAlLapVzhNT2J2sCWXMqe2x7g7klEr3N6+p8AAAAAAAAYAAABwwCBKiamcBn5fj0oQ3WcAU+twE4XemcK4G2nlprqBKAAAAAAABgAAAAwCYIUh0y2bkIH8BVZ/evuFulOCxOyGr/rvZnR2k/9aAAAAAAAGAAAABFCoAAAAAAAAIgAgvXwvxBU2X03+pufsytFJ2dS4BKVXIKMQmyxUXTbPJPmA8PoCAAAAABYAFCMDXGnefAb487YxeNjnpbUzH+pEQEtMAAAAAAAWABT+rq2LTo+bnAo3ZQoeUg0F6xVZbIx3EwIAAAAAIgAgfAYV/vqzwEWHS6kVMjA1yQRbIQqq//o7m4ik0eSSlasAAAAAAAEBKzb0VQMAAAAAIgAgEyIAQqFnv+D0rMmVvusK3TC6fPyFk7aU1PZ8+Ttm23IBAwQBAAAAAQXBUiEDNWoO4CCloCul5eCLd1+XLPxP4LMIsUy+XM01wlm59wIhAqQ3tGeAeMBPPR26fn0kuL0CS0AybrDlu8NwIzFOOukzIQJoBBIwDWTXwjMse2MiB8/kIcFOZACiADcmZltiEl85N1OuZHapFIe9/DRONZOp5OAQ6RCrIDclCDEjiKxrdqkUJs2E27SQYhbh4yxNkO+lDnFqCCaIrGyTa3apFBtcD9uL3TRJt1uCIj2J8Ub4YjvgiKxsk1OHZ1ayaCIGAmgEEjANZNfCMyx7YyIHz+QhwU5kAKIANyZmW2ISXzk3CO9FHBcBAAAAIgYCpDe0Z4B4wE89Hbp+fSS4vQJLQDJusOW7w3AjMU466TMIW+FtfgEAAAAiBgM1ag7gIKWgK6Xl4It3X5cs/E/gswixTL5czTXCWbn3AgjDFaC/AQAAAAABASs2rG0BAAAAACIAIICUwlAfLlUkhU44Hpkj/LEDNAdwME4fm3jtWfXwMwL7AQMEAQAAAAEFwVIhAgSNQIWSNnYSrfEl8juzTKw9o3BjYQ+DgbyizShqKzIcIQN+tRtybpIxVK9IdwxsTxFgy2YsiQqtnGvnowXelPblJiEC25bXunBKDpmrAvXiBbJ/+x9Oo5pL+8FhKgAqXSesn0VTrmR2qRTWWGTXm1UxE4rqqD2FkiKS94r8YYisa3apFCBven2wd5QCFoHAl/iRHg+9SJkgiKxsk2t2qRRP/mE3OesTO6kSJOgsBAoyLTfO8oisbJNTh2dWsmgiBgIEjUCFkjZ2Eq3xJfI7s0ysPaNwY2EPg4G8os0oaisyHAjDFaC/AAAAACIGAtuW17pwSg6ZqwL14gWyf/sfTqOaS/vBYSoAKl0nrJ9FCO9FHBcAAAAAIgYDfrUbcm6SMVSvSHcMbE8RYMtmLIkKrZxr56MF3pT25SYIW+FtfgAAAAAAAQErtgyYAAAAAAAiACCAlMJQHy5VJIVOOB6ZI/yxAzQHcDBOH5t47Vn18DMC+wEDBAEAAAABBcFSIQIEjUCFkjZ2Eq3xJfI7s0ysPaNwY2EPg4G8os0oaisyHCEDfrUbcm6SMVSvSHcMbE8RYMtmLIkKrZxr56MF3pT25SYhAtuW17pwSg6ZqwL14gWyf/sfTqOaS/vBYSoAKl0nrJ9FU65kdqkU1lhk15tVMROK6qg9hZIikveK/GGIrGt2qRQgb3p9sHeUAhaBwJf4kR4PvUiZIIisbJNrdqkUT/5hNznrEzupEiToLAQKMi03zvKIrGyTU4dnVrJoIgYCBI1AhZI2dhKt8SXyO7NMrD2jcGNhD4OBvKLNKGorMhwIwxWgvwAAAAAiBgLblte6cEoOmasC9eIFsn/7H06jmkv7wWEqACpdJ6yfRQjvRRwXAAAAACIGA361G3JukjFUr0h3DGxPEWDLZiyJCq2ca+ejBd6U9uUmCFvhbX4AAAAAACICArFlfWaPsqMsvdC+/3Hise+ubUHtj4n5Uz7qaI0bCfCWCBhRVloBAAAAIgICtg6ewcvt4XnF35qT+j9KoCYt4+vS8hXmOn1NsO/QppUIgryGbgEAAAAiAgOJmnB0i/XOb8ITGRA3itrYfvWx6/B8PGMiu2SYfOACFQhTR/BbAQAAAAAAACICAr+BTfGuO1VRPxE1DJoFIsH1Vu5Dk5lSullVQjCXjVlICEPuDksBAAAAIgIC+G7/TA9DNgnMf4Nup2Py3XAF8UCLmziV3Vw4Z2KsJcwIpbzhFQEAAAAiAgOpos5KhVRQaTPJTi3mk12g5sApoQNVGdOpMcMmn7C7gwieIH0+AQAAAAA=").unwrap(); assert!(check_spend_transaction_size(&revaultd, tx)); diff --git a/src/database/actions.rs b/src/database/actions.rs index 8b7af898..5d28c9d8 100644 --- a/src/database/actions.rs +++ b/src/database/actions.rs @@ -1008,7 +1008,8 @@ pub fn db_mark_rebroadcastable_spend( mod test { use super::*; use crate::database::schema::DbSpendTransaction; - use crate::utils::test_utils::{dummy_revaultd, test_datadir, UserRole}; + use crate::revaultd::UserRole; + use crate::utils::test_utils::{dummy_revaultd, test_datadir}; use revault_tx::{ bitcoin::{ Network, OutPoint, PrivateKey as BitcoinPrivKey, PublicKey as BitcoinPubKey, @@ -1100,7 +1101,7 @@ mod test { #[test] fn test_db_creation() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); create_db(&mut revaultd).unwrap(); // There must be a wallet entry now, and there is only one so its id must @@ -1129,7 +1130,7 @@ mod test { #[test] fn test_db_fetch_deposits() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_path = revaultd.db_file(); setup_db(&mut revaultd).unwrap(); @@ -1235,7 +1236,7 @@ mod test { #[test] fn test_db_store_presigned_txs() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_path = revaultd.db_file(); let secp_ctx = secp256k1::Secp256k1::new(); @@ -1535,7 +1536,7 @@ mod test { #[test] fn test_db_confirm_unvault() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_path = revaultd.db_file(); setup_db(&mut revaultd).unwrap(); @@ -1610,7 +1611,7 @@ mod test { #[test] fn test_db_concurrent_write() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_path = revaultd.db_file(); let secp_ctx = secp256k1::Secp256k1::new(); @@ -1688,7 +1689,7 @@ mod test { #[test] fn test_db_spend_storage() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_path = revaultd.db_file(); let fresh_cancel_tx = CancelTransaction::from_psbt_str("cHNidP8BAF4CAAAAARoHs0elD2sCfWV4+b7PH3aRA+BkRVNf3m/P+Epjx2fNAAAAAAD9////AdLKAgAAAAAAIgAgB6abzQJ4vo5CO9XW3r3JnNumTwlpQbZm9FVICsLHPYQAAAAAAAEBK0ANAwAAAAAAIgAglEs6phQpv+twnAQSdjDvAEic65OtUIijeePBzAAqr50BAwSBAAAAAQWrIQO4lrAuffeRLuEEuwp2hAMZIPmqaHMTUySM3OwdA2hIW6xRh2R2qRTflccImFIy5NdTqwPuPZFB7g1pvYisa3apFOQxXoLeQv/aDFfav/l6YnYRKt+1iKxsk1KHZ1IhA32Q1DEqQ/kUP2MvQYFW46RCexZ5aYk17Arhp01th+37IQNrXQtfIXQdrv+RyyHLilJsb4ujlUMddG9X2jYkeXiWoFKvA3nxALJoIgYCEnb0lxeNI9466wDX+tqlq23zYNacTlLVLLLxtcVobG0INaO2mQoAAAAAAQFHUiED35umh5GhiToV6GS7lTokWfq/Rvy+rRI9XMQuf+foOoEhA9GtXpHhUvxcj9DJWbaRvz59CNsMwH2NEvmRa8gc2WRkUq4iAgISdvSXF40j3jrrANf62qWrbfNg1pxOUtUssvG1xWhsbQg1o7aZCgAAAAA=").unwrap(); let fresh_unvault_tx = UnvaultTransaction::from_psbt_str("cHNidP8BAIkCAAAAAfF2iPeJqz13zFlW6eLAM+uDu5IhUqcQxtMWQx7z5Y8lAAAAAAD9////AkANAwAAAAAAIgAgKb0SdnuqeHAJpRuZTbk3r81qbXpuHrMEmxT9Kph47HQwdQAAAAAAACIAIIMbpoIz4DI+aB1p/EJLyqjyDdDeZ7gG8kPhRIDiWaY8AAAAAAABASuIlAMAAAAAACIAIA9CgZ1cg/hn3iy3buDZvU5zUnQ9NzutToR/r42YZyu3AQMEAQAAAAEFR1IhA9P6hV8yf6HkNofzleom06eqkUxZayWHJnOMNlMtqvD3IQJo5Mj6Wf3ktrwEB3IQXFmgApibojplpNykg0hA8XV6SFKuIgYCEnb0lxeNI9466wDX+tqlq23zYNacTlLVLLLxtcVobG0INaO2mQoAAAAAAQGqIQMfu47eLiYeHN6Y3C1Vk0ckgmWifMy5IUhaPHbNELV93axRh2R2qRTtiGxBD5KrMQQU6UGx2zsKMMf6nIisa3apFCDKte9IuDeF0D4GA/JRUNX4xgt+iKxsk1KHZ1IhAzTPPnjrvzPFmi+raNR6sY8WTt1KNusVwp82uWebzWDwIQKl21mZX7WAQhRvdhhwqUAuQfIemg9zkTCCyMQ+Q8CVFVKvAqUBsmgiAgISdvSXF40j3jrrANf62qWrbfNg1pxOUtUssvG1xWhsbQg1o7aZCgAAAAABASUhAx+7jt4uJh4c3pjcLVWTRySCZaJ8zLkhSFo8ds0QtX3drFGHIgICEnb0lxeNI9466wDX+tqlq23zYNacTlLVLLLxtcVobG0INaO2mQoAAAAA").unwrap(); @@ -1956,7 +1957,7 @@ mod test { #[test] fn test_db_update_vault_status() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_path = revaultd.db_file(); setup_db(&mut revaultd).unwrap(); diff --git a/src/database/interface.rs b/src/database/interface.rs index fb1bb71b..31751031 100644 --- a/src/database/interface.rs +++ b/src/database/interface.rs @@ -943,7 +943,8 @@ pub fn db_vaults_with_txids_in_period( mod test { use super::*; use crate::database::actions::{db_confirm_deposit, db_insert_new_unconfirmed_vault, setup_db}; - use crate::utils::test_utils::{dummy_revaultd, test_datadir, UserRole}; + use crate::revaultd::UserRole; + use crate::utils::test_utils::{dummy_revaultd, test_datadir}; use revault_tx::{bitcoin::OutPoint, transactions::transaction_chain}; use std::{fs, str::FromStr}; @@ -967,7 +968,7 @@ mod test { #[test] fn test_db_vaults_with_txids_in_period() { let datadir = test_datadir(); - let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::ManagerStakeholder); + let mut revaultd = dummy_revaultd(datadir.clone(), UserRole::StakeholderManager); let db_path = revaultd.db_file(); setup_db(&mut revaultd).unwrap(); let genesis_timestamp: u32 = 1231006505; diff --git a/src/jsonrpc/server.rs b/src/jsonrpc/server.rs index fc648145..a99b7078 100644 --- a/src/jsonrpc/server.rs +++ b/src/jsonrpc/server.rs @@ -415,7 +415,8 @@ pub fn rpcserver_loop( #[cfg(test)] mod tests { use super::{read_bytes_from_stream, rpcserver_loop, rpcserver_setup, trimmed}; - use crate::utils::test_utils::{dummy_rpcutil, test_datadir, UserRole}; + use crate::revaultd::UserRole; + use crate::utils::test_utils::{dummy_rpcutil, test_datadir}; use std::{ fs, @@ -431,7 +432,7 @@ mod tests { #[test] fn simple_write_recv() { let datadir = test_datadir(); - let rpcutils = dummy_rpcutil(datadir.clone(), UserRole::ManagerStakeholder); + let rpcutils = dummy_rpcutil(datadir.clone(), UserRole::StakeholderManager); let revaultd_datadir = rpcutils.revaultd.read().unwrap().data_dir.clone(); let mut rpc_socket_path = revaultd_datadir.clone(); rpc_socket_path.push("revaultd_rpc"); diff --git a/src/revaultd.rs b/src/revaultd.rs index ea61b165..c389a9ef 100644 --- a/src/revaultd.rs +++ b/src/revaultd.rs @@ -276,6 +276,40 @@ pub struct BlockchainTip { pub hash: BlockHash, } +#[derive(Debug, Clone)] +pub enum UserRole { + Stakeholder, + Manager, + StakeholderManager, +} + +impl FromStr for UserRole { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "stakeholder" => Ok(Self::Stakeholder), + "stakeholdermanager" => Ok(Self::StakeholderManager), + "manager" => Ok(Self::Manager), + _ => Err(format!("Unknown role: {}", s)), + } + } +} + +impl fmt::Display for UserRole { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match *self { + Self::Stakeholder => "stakeholder", + Self::Manager => "manager", + Self::StakeholderManager => "stakeholdermanager", + } + ) + } +} + /// Our global state pub struct RevaultD { // Bitcoind stuff diff --git a/src/utils.rs b/src/utils.rs index 1c15990f..7a52c2b2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -4,7 +4,7 @@ pub mod test_utils { use crate::{ bitcoind::{interface::WalletTransaction, BitcoindError}, database::interface::db_exec, - revaultd::{RevaultD, VaultStatus}, + revaultd::{RevaultD, UserRole, VaultStatus}, threadmessages::{ BitcoindMessageOut, BitcoindSender, BitcoindThread, SigFetcherMessageOut, }, @@ -24,13 +24,6 @@ pub mod test_utils { use rusqlite::params; - #[derive(Debug, Clone)] - pub enum UserRole { - Stakeholder, - Manager, - ManagerStakeholder, - } - pub fn test_datadir() -> PathBuf { static mut COUNTER: u64 = 0; unsafe { @@ -76,7 +69,7 @@ addr = "127.0.0.1:8332" match role { UserRole::Stakeholder => config += stake_config, UserRole::Manager => config += man_config, - UserRole::ManagerStakeholder => { + UserRole::StakeholderManager => { config += stake_config; config += man_config; } diff --git a/tests/test_rpc.py b/tests/test_rpc.py index 95dd5b3e..70bc954f 100644 --- a/tests/test_rpc.py +++ b/tests/test_rpc.py @@ -27,6 +27,7 @@ def test_getinfo(revaultd_manager, bitcoind): assert res["vaults"] == 0 # revaultd_manager always deploys with N = 2, M = 3, threshold = M assert res["managers_threshold"] == 3 + assert res["participant_type"] == "manager" # test descriptors: RPC call & which Revaultd's were configured assert res["descriptors"]["cpfp"] == revaultd_manager.cpfp_desc assert res["descriptors"]["deposit"] == revaultd_manager.deposit_desc