diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index c7accd9df0d..fc42e130220 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -583,7 +583,10 @@ where Utc::now(), )); - let tip_height = self.latest_chain_tip.best_tip_height().unwrap_or(Height::MIN); + let tip_height = self + .latest_chain_tip + .best_tip_height() + .unwrap_or(Height::MIN); let testnet = self.network.is_a_test_network(); // This field is behind the `ENABLE_WALLET` feature flag in zcashd: @@ -593,7 +596,8 @@ where // For compatibility, we keep the field in the response, but always return 0. let pay_tx_fee = 0.0; - let relay_fee = zebra_chain::transaction::zip317::MIN_MEMPOOL_TX_FEE_RATE as f64 / (zebra_chain::amount::COIN as f64); + let relay_fee = zebra_chain::transaction::zip317::MIN_MEMPOOL_TX_FEE_RATE as f64 + / (zebra_chain::amount::COIN as f64); let difficulty = chain_tip_difficulty(self.network.clone(), self.state.clone()).await?; let response = GetInfo { diff --git a/zebra-rpc/src/methods/tests/prop.rs b/zebra-rpc/src/methods/tests/prop.rs index 0200f88a300..b7df3b30127 100644 --- a/zebra-rpc/src/methods/tests/prop.rs +++ b/zebra-rpc/src/methods/tests/prop.rs @@ -24,6 +24,7 @@ use zebra_chain::{ }; use zebra_consensus::ParameterCheckpoint; +use zebra_network::address_book_peers::MockAddressBookPeers; use zebra_node_services::mempool; use zebra_state::{BoxError, GetBlockTemplateChainInfo}; @@ -968,6 +969,7 @@ fn mock_services( zebra_state::ReadRequest, >, Tip, + MockAddressBookPeers, >, tokio::task::JoinHandle<()>, ) @@ -978,7 +980,7 @@ where let state = MockService::build().for_prop_tests(); let (rpc, mempool_tx_queue) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", network, false, @@ -986,6 +988,8 @@ where mempool.clone(), Buffer::new(state.clone(), 1), chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); (mempool, state, rpc, mempool_tx_queue) diff --git a/zebra-rpc/src/methods/tests/snapshot.rs b/zebra-rpc/src/methods/tests/snapshot.rs index 328d3d0f5a4..5e2754b2382 100644 --- a/zebra-rpc/src/methods/tests/snapshot.rs +++ b/zebra-rpc/src/methods/tests/snapshot.rs @@ -25,6 +25,7 @@ use zebra_chain::{ serialization::ZcashDeserializeInto, subtree::NoteCommitmentSubtreeData, }; +use zebra_network::address_book_peers::MockAddressBookPeers; use zebra_node_services::BoxError; use zebra_state::{ReadRequest, ReadResponse, MAX_ON_DISK_HEIGHT}; use zebra_test::mock_service::MockService; @@ -116,6 +117,8 @@ async fn test_z_get_treestate() { Buffer::new(MockService::build().for_unit_tests::<_, _, BoxError>(), 1), state, tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Request the treestate by a hash. @@ -198,7 +201,7 @@ async fn test_rpc_response_data_for_network(network: &Network) { // Init RPC let (rpc, _rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "/Zebra:RPC test/", network.clone(), false, @@ -206,6 +209,8 @@ async fn test_rpc_response_data_for_network(network: &Network) { Buffer::new(mempool.clone(), 1), read_state, latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // We only want a snapshot of the `getblocksubsidy` and `getblockchaininfo` methods for the non-default Testnet (with an NU6 activation height). @@ -220,7 +225,10 @@ async fn test_rpc_response_data_for_network(network: &Network) { } // `getinfo` - let get_info = rpc.get_info().expect("We should have a GetInfo struct"); + let get_info = rpc + .get_info() + .await + .expect("We should have a GetInfo struct"); snapshot_rpc_getinfo(get_info, &settings); // `getblockchaininfo` @@ -522,7 +530,7 @@ async fn test_mocked_rpc_response_data_for_network(network: &Network) { let mempool = MockService::build().for_unit_tests(); let (rpc, _) = RpcImpl::new( - "RPC test", + "0.0.1", "/Zebra:RPC test/", network.clone(), false, @@ -530,6 +538,8 @@ async fn test_mocked_rpc_response_data_for_network(network: &Network) { mempool, state.clone(), latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Test the response format from `z_getsubtreesbyindex` for Sapling. @@ -599,6 +609,9 @@ fn snapshot_rpc_getinfo(info: GetInfo, settings: &insta::Settings) { // replace with: "[SubVersion]" }), + ".errorstimestamp" => dynamic_redaction(|_value, _path| { + "[LastErrorTimestamp]" + }), }) }); } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_info@mainnet_10.snap index 884da201ee4..85f77bdc486 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_info@mainnet_10.snap @@ -1,9 +1,18 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs -assertion_line: 161 expression: info --- { - "build": "vRPC test", - "subversion": "[SubVersion]" + "version": 100, + "build": "v0.0.1", + "subversion": "[SubVersion]", + "protocolversion": 170120, + "blocks": 10, + "connections": 0, + "difficulty": 1.0, + "testnet": false, + "paytxfee": 0.0, + "relayfee": 0.000001, + "errors": "no errors", + "errorstimestamp": "[LastErrorTimestamp]" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_info@testnet_10.snap index 884da201ee4..c1197ff0190 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_info@testnet_10.snap @@ -1,9 +1,18 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs -assertion_line: 161 expression: info --- { - "build": "vRPC test", - "subversion": "[SubVersion]" + "version": 100, + "build": "v0.0.1", + "subversion": "[SubVersion]", + "protocolversion": 170120, + "blocks": 10, + "connections": 0, + "difficulty": 1.0, + "testnet": true, + "paytxfee": 0.0, + "relayfee": 0.000001, + "errors": "no errors", + "errorstimestamp": "[LastErrorTimestamp]" } diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index a25b399c697..4ae9cfb1aef 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -14,9 +14,10 @@ use zebra_chain::{ serialization::{ZcashDeserializeInto, ZcashSerialize}, transaction::UnminedTxId, }; +use zebra_network::address_book_peers::MockAddressBookPeers; use zebra_node_services::BoxError; -use zebra_state::{LatestChainTip, ReadStateService}; +use zebra_state::{GetBlockTemplateChainInfo, LatestChainTip, ReadStateService}; use zebra_test::mock_service::MockService; use super::super::*; @@ -29,7 +30,7 @@ async fn rpc_getinfo() { let mut state: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests(); let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "/Zebra:RPC test/", Mainnet, false, @@ -37,13 +38,36 @@ async fn rpc_getinfo() { Buffer::new(mempool.clone(), 1), Buffer::new(state.clone(), 1), NoChainTip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); - let get_info = rpc.get_info().expect("We should have a GetInfo struct"); + let getinfo_future = tokio::spawn(async move { rpc.get_info().await }); + + // Make the mock service respond with + let response_handler = state + .expect_request(zebra_state::ReadRequest::ChainInfo) + .await; + response_handler.respond(zebra_state::ReadResponse::ChainInfo( + GetBlockTemplateChainInfo { + tip_hash: Mainnet.genesis_hash(), + tip_height: Height::MIN, + history_tree: Default::default(), + expected_difficulty: Default::default(), + cur_time: zebra_chain::serialization::DateTime32::now(), + min_time: zebra_chain::serialization::DateTime32::now(), + max_time: zebra_chain::serialization::DateTime32::now(), + }, + )); + + let get_info = getinfo_future + .await + .expect("getinfo future should not panic") + .expect("getinfo future should not return an error"); // make sure there is a `build` field in the response, // and that is equal to the provided string, with an added 'v' version prefix. - assert_eq!(get_info.build, "vRPC test"); + assert_eq!(get_info.build, "v0.0.1"); // make sure there is a `subversion` field, // and that is equal to the Zebra user agent. @@ -120,7 +144,7 @@ async fn rpc_getblock() { // Init RPC let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -128,6 +152,8 @@ async fn rpc_getblock() { Buffer::new(mempool.clone(), 1), read_state.clone(), latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Make height calls with verbosity=0 and check response @@ -461,7 +487,7 @@ async fn rpc_getblock_parse_error() { // Init RPC let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -469,6 +495,8 @@ async fn rpc_getblock_parse_error() { Buffer::new(mempool.clone(), 1), Buffer::new(state.clone(), 1), NoChainTip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Make sure we get an error if Zebra can't parse the block height. @@ -504,7 +532,7 @@ async fn rpc_getblock_missing_error() { // Init RPC let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -512,6 +540,8 @@ async fn rpc_getblock_missing_error() { Buffer::new(mempool.clone(), 1), Buffer::new(state.clone(), 1), NoChainTip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Make sure Zebra returns the correct error code `-8` for missing blocks @@ -566,7 +596,7 @@ async fn rpc_getblockheader() { // Init RPC let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -574,6 +604,8 @@ async fn rpc_getblockheader() { Buffer::new(mempool.clone(), 1), read_state.clone(), latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Make height calls with verbose=false and check response @@ -677,7 +709,7 @@ async fn rpc_getbestblockhash() { // Init RPC let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -685,6 +717,8 @@ async fn rpc_getbestblockhash() { Buffer::new(mempool.clone(), 1), read_state, latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Get the tip hash using RPC method `get_best_block_hash` @@ -723,7 +757,7 @@ async fn rpc_getrawtransaction() { // Init RPC let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -731,6 +765,8 @@ async fn rpc_getrawtransaction() { Buffer::new(mempool.clone(), 1), read_state.clone(), latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // Test case where transaction is in mempool. @@ -899,7 +935,7 @@ async fn rpc_getaddresstxids_invalid_arguments() { zebra_state::populated_state(blocks.clone(), &Mainnet).await; let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -907,6 +943,8 @@ async fn rpc_getaddresstxids_invalid_arguments() { Buffer::new(mempool.clone(), 1), Buffer::new(read_state.clone(), 1), latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // call the method with an invalid address string @@ -1048,7 +1086,7 @@ async fn rpc_getaddresstxids_response_with( let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests(); let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", network.clone(), false, @@ -1056,6 +1094,8 @@ async fn rpc_getaddresstxids_response_with( Buffer::new(mempool.clone(), 1), Buffer::new(read_state.clone(), 1), latest_chain_tip.clone(), + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // call the method with valid arguments @@ -1100,7 +1140,7 @@ async fn rpc_getaddressutxos_invalid_arguments() { let mut state: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests(); let rpc = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -1108,6 +1148,8 @@ async fn rpc_getaddressutxos_invalid_arguments() { Buffer::new(mempool.clone(), 1), Buffer::new(state.clone(), 1), NoChainTip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // call the method with an invalid address string @@ -1145,7 +1187,7 @@ async fn rpc_getaddressutxos_response() { zebra_state::populated_state(blocks.clone(), &Mainnet).await; let rpc = RpcImpl::new( - "RPC test", + "0.0.1", "RPC test", Mainnet, false, @@ -1153,6 +1195,8 @@ async fn rpc_getaddressutxos_response() { Buffer::new(mempool.clone(), 1), Buffer::new(read_state.clone(), 1), latest_chain_tip, + MockAddressBookPeers::new(vec![]), + crate::methods::LoggedLastEvent::new(None.into()), ); // call the method with a valid address diff --git a/zebra-rpc/src/server/tests/vectors.rs b/zebra-rpc/src/server/tests/vectors.rs index 6cb83f98326..b65f9a2ca0f 100644 --- a/zebra-rpc/src/server/tests/vectors.rs +++ b/zebra-rpc/src/server/tests/vectors.rs @@ -57,6 +57,7 @@ async fn rpc_server_spawn() { NoChainTip, Mainnet, None, + crate::methods::LoggedLastEvent::new(None.into()), ); info!("spawned RPC server, checking services..."); @@ -117,6 +118,7 @@ async fn rpc_spawn_unallocated_port(do_shutdown: bool) { NoChainTip, Mainnet, None, + crate::methods::LoggedLastEvent::new(None.into()), ) .await .expect(""); @@ -173,6 +175,7 @@ async fn rpc_server_spawn_port_conflict() { NoChainTip, Mainnet, None, + crate::methods::LoggedLastEvent::new(None.into()), ) .await; @@ -193,6 +196,7 @@ async fn rpc_server_spawn_port_conflict() { NoChainTip, Mainnet, None, + crate::methods::LoggedLastEvent::new(None.into()), ) .await; diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index 757a61059cf..1201bcd6e04 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -1600,6 +1600,9 @@ async fn rpc_endpoint(parallel_cpu_threads: bool) -> Result<()> { // Create an http client let client = RpcRequestClient::new(rpc_address); + // Run `zebrad` for a few seconds before testing the endpoint + std::thread::sleep(LAUNCH_DELAY); + // Make the call to the `getinfo` RPC method let res = client.call("getinfo", "[]".to_string()).await?;