fix(rpc): Fix some RPC response formats to match `zcashd` (#4217)
* Match `zcashd`'s version format in `getinfo` * Remove an incorrect array wrapper in getaddressbalance * Use a stable sort order in getrawmempool Because we can't match zcashd's arbitrary order, and probably shouldn't try to. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
83d26890f5
commit
7506655774
|
@ -19,7 +19,6 @@ use tower::{buffer::Buffer, Service, ServiceExt};
|
||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
|
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
amount::{Amount, NonNegative},
|
|
||||||
block::{self, Height, SerializedBlock},
|
block::{self, Height, SerializedBlock},
|
||||||
chain_tip::ChainTip,
|
chain_tip::ChainTip,
|
||||||
parameters::{ConsensusBranchId, Network, NetworkUpgrade},
|
parameters::{ConsensusBranchId, Network, NetworkUpgrade},
|
||||||
|
@ -273,8 +272,15 @@ where
|
||||||
{
|
{
|
||||||
let runner = Queue::start();
|
let runner = Queue::start();
|
||||||
|
|
||||||
|
let mut app_version = app_version.to_string();
|
||||||
|
|
||||||
|
// Match zcashd's version format, if the version string has anything in it
|
||||||
|
if !app_version.is_empty() && !app_version.starts_with('v') {
|
||||||
|
app_version.insert(0, 'v');
|
||||||
|
}
|
||||||
|
|
||||||
let rpc_impl = RpcImpl {
|
let rpc_impl = RpcImpl {
|
||||||
app_version: app_version.to_string(),
|
app_version,
|
||||||
mempool: mempool.clone(),
|
mempool: mempool.clone(),
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
latest_chain_tip: latest_chain_tip.clone(),
|
latest_chain_tip: latest_chain_tip.clone(),
|
||||||
|
@ -431,9 +437,9 @@ where
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
zebra_state::ReadResponse::AddressBalance(balance) => {
|
zebra_state::ReadResponse::AddressBalance(balance) => Ok(AddressBalance {
|
||||||
Ok(AddressBalance { balance })
|
balance: u64::from(balance),
|
||||||
}
|
}),
|
||||||
_ => unreachable!("Unexpected response from state service: {response:?}"),
|
_ => unreachable!("Unexpected response from state service: {response:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -556,10 +562,16 @@ where
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
mempool::Response::TransactionIds(unmined_transaction_ids) => {
|
mempool::Response::TransactionIds(unmined_transaction_ids) => {
|
||||||
Ok(unmined_transaction_ids
|
let mut tx_ids: Vec<String> = unmined_transaction_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|id| id.mined_id().encode_hex())
|
.map(|id| id.mined_id().encode_hex())
|
||||||
.collect())
|
.collect();
|
||||||
|
|
||||||
|
// Sort returned transaction IDs in numeric/string order.
|
||||||
|
// (zcashd's sort order appears arbitrary.)
|
||||||
|
tx_ids.sort();
|
||||||
|
|
||||||
|
Ok(tx_ids)
|
||||||
}
|
}
|
||||||
_ => unreachable!("unmatched response to a transactionids request"),
|
_ => unreachable!("unmatched response to a transactionids request"),
|
||||||
}
|
}
|
||||||
|
@ -730,7 +742,7 @@ where
|
||||||
let height = utxo_data.2.height().0;
|
let height = utxo_data.2.height().0;
|
||||||
let output_index = utxo_data.2.output_index().as_usize();
|
let output_index = utxo_data.2.output_index().as_usize();
|
||||||
let script = utxo_data.3.lock_script.to_string();
|
let script = utxo_data.3.lock_script.to_string();
|
||||||
let satoshis = i64::from(utxo_data.3.value);
|
let satoshis = u64::from(utxo_data.3.value);
|
||||||
|
|
||||||
let entry = GetAddressUtxos {
|
let entry = GetAddressUtxos {
|
||||||
address,
|
address,
|
||||||
|
@ -809,7 +821,7 @@ impl AddressStrings {
|
||||||
/// The transparent balance of a set of addresses.
|
/// The transparent balance of a set of addresses.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, serde::Serialize)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, serde::Serialize)]
|
||||||
pub struct AddressBalance {
|
pub struct AddressBalance {
|
||||||
balance: Amount<NonNegative>,
|
balance: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A hex-encoded [`ConsensusBranchId`] string.
|
/// A hex-encoded [`ConsensusBranchId`] string.
|
||||||
|
@ -899,7 +911,7 @@ pub struct GetAddressUtxos {
|
||||||
#[serde(rename = "outputIndex")]
|
#[serde(rename = "outputIndex")]
|
||||||
output_index: usize,
|
output_index: usize,
|
||||||
script: String,
|
script: String,
|
||||||
satoshis: i64,
|
satoshis: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetRawTransaction {
|
impl GetRawTransaction {
|
||||||
|
|
|
@ -328,10 +328,11 @@ proptest! {
|
||||||
);
|
);
|
||||||
|
|
||||||
let call_task = tokio::spawn(rpc.get_raw_mempool());
|
let call_task = tokio::spawn(rpc.get_raw_mempool());
|
||||||
let expected_response: Vec<String> = transaction_ids
|
let mut expected_response: Vec<String> = transaction_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|id| id.mined_id().encode_hex())
|
.map(|id| id.mined_id().encode_hex())
|
||||||
.collect();
|
.collect();
|
||||||
|
expected_response.sort();
|
||||||
|
|
||||||
mempool
|
mempool
|
||||||
.expect_request(mempool::Request::TransactionIds)
|
.expect_request(mempool::Request::TransactionIds)
|
||||||
|
@ -632,7 +633,7 @@ proptest! {
|
||||||
// Check that response contains the expected balance
|
// Check that response contains the expected balance
|
||||||
let received_balance = response?;
|
let received_balance = response?;
|
||||||
|
|
||||||
prop_assert_eq!(received_balance, AddressBalance { balance });
|
prop_assert_eq!(received_balance, AddressBalance { balance: balance.into() });
|
||||||
|
|
||||||
// Check no further requests were made during this test
|
// Check no further requests were made during this test
|
||||||
mempool.expect_no_requests().await?;
|
mempool.expect_no_requests().await?;
|
||||||
|
|
|
@ -38,8 +38,8 @@ async fn rpc_getinfo() {
|
||||||
let get_info = rpc.get_info().expect("We should have a GetInfo struct");
|
let get_info = rpc.get_info().expect("We should have a GetInfo struct");
|
||||||
|
|
||||||
// make sure there is a `build` field in the response,
|
// make sure there is a `build` field in the response,
|
||||||
// and that is equal to the provided string.
|
// and that is equal to the provided string, with an added 'v' version prefix.
|
||||||
assert_eq!(get_info.build, "RPC test");
|
assert_eq!(get_info.build, "vRPC test");
|
||||||
|
|
||||||
// make sure there is a `subversion` field,
|
// make sure there is a `subversion` field,
|
||||||
// and that is equal to the Zebra user agent.
|
// and that is equal to the Zebra user agent.
|
||||||
|
|
Loading…
Reference in New Issue