Test `z_getsubtreesbyindex` using a lightwalletd gRPC request (#7521)
* Add lightwalletd's protobuf types * Don't explicitly derive `Eq` for enums I got bitten by this bug: https://github.com/tokio-rs/prost/issues/332 when I added the enum `ShieldedProtocol` to the file `service.proto`. The problem is that `prost` implicitly derives `Eq` for enums, so deriving it explicitly via `type_attribute` causes a conflict. Lukily, there is another method `message_attribute` that operates only on messages and not enums. * Test the `z_getsubtreesbyindex` RPC * Fix a typo * Add test vectors
This commit is contained in:
parent
70d34a6d4b
commit
dc6aa708d0
|
@ -1795,6 +1795,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
|
@ -5814,6 +5820,7 @@ dependencies = [
|
|||
"dirs",
|
||||
"futures",
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"howudoin",
|
||||
"humantime-serde",
|
||||
"hyper",
|
||||
|
|
|
@ -231,6 +231,7 @@ tonic-build = { version = "0.10.0", optional = true }
|
|||
[dev-dependencies]
|
||||
abscissa_core = { version = "0.7.0", features = ["testing"] }
|
||||
hex = "0.4.3"
|
||||
hex-literal = "0.4.1"
|
||||
jsonrpc-core = "18.0.0"
|
||||
once_cell = "1.18.0"
|
||||
regex = "1.9.5"
|
||||
|
|
|
@ -46,7 +46,7 @@ fn main() {
|
|||
// The lightwalletd gRPC types don't use floats or complex collections,
|
||||
// so we can derive `Eq` as well as the default generated `PartialEq` derive.
|
||||
// This fixes `clippy::derive_partial_eq_without_eq` warnings.
|
||||
.type_attribute(".", "#[derive(Eq)]")
|
||||
.message_attribute(".", "#[derive(Eq)]")
|
||||
.compile(
|
||||
&["tests/common/lightwalletd/proto/service.proto"],
|
||||
&["tests/common/lightwalletd/proto"],
|
||||
|
|
|
@ -117,6 +117,27 @@ message TreeState {
|
|||
string tree = 5; // sapling commitment tree state
|
||||
}
|
||||
|
||||
enum ShieldedProtocol {
|
||||
sapling = 0;
|
||||
orchard = 1;
|
||||
}
|
||||
|
||||
// Request type for `GetSubtreeRoots`
|
||||
message GetSubtreeRootsArg {
|
||||
uint32 startIndex = 1; // Index identifying where to start returning subtree roots.
|
||||
ShieldedProtocol shieldedProtocol = 2; // Shielded protocol to return subtree roots for.
|
||||
uint32 maxEntries = 3; // Maximum number of entries to return, or 0 for all entries.
|
||||
}
|
||||
|
||||
|
||||
// Response type for `GetSubtreeRoots`.
|
||||
// The actual response contains a stream of `SubtreeRoot`s.
|
||||
message SubtreeRoot {
|
||||
bytes rootHash = 2; // The 32-byte Merkle root of the subtree.
|
||||
bytes completingBlockHash = 3; // The hash of the block that completed this subtree.
|
||||
uint64 completingBlockHeight = 4; // The height of the block that completed this subtree in the main chain.
|
||||
}
|
||||
|
||||
// Results are sorted by height, which makes it easy to issue another
|
||||
// request that picks up from where the previous left off.
|
||||
message GetAddressUtxosArg {
|
||||
|
@ -175,6 +196,10 @@ service CompactTxStreamer {
|
|||
// The block can be specified by either height or hash.
|
||||
rpc GetTreeState(BlockID) returns (TreeState) {}
|
||||
|
||||
// Returns a stream of information about roots of subtrees of the Sapling
|
||||
// and Orchard note commitment trees.
|
||||
rpc GetSubtreeRoots(GetSubtreeRootsArg) returns (stream SubtreeRoot) {}
|
||||
|
||||
rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {}
|
||||
rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
//! purposes.
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
use hex_literal::hex;
|
||||
|
||||
use zebra_chain::{
|
||||
block::Block,
|
||||
|
@ -50,7 +51,8 @@ use crate::common::{
|
|||
sync::wait_for_zebrad_and_lightwalletd_sync,
|
||||
wallet_grpc::{
|
||||
connect_to_lightwalletd, Address, AddressList, BlockId, BlockRange, ChainSpec, Empty,
|
||||
GetAddressUtxosArg, TransparentAddressBlockFilter, TxFilter,
|
||||
GetAddressUtxosArg, GetSubtreeRootsArg, ShieldedProtocol,
|
||||
TransparentAddressBlockFilter, TxFilter,
|
||||
},
|
||||
},
|
||||
test_type::TestType::UpdateCachedState,
|
||||
|
@ -337,6 +339,78 @@ pub async fn run() -> Result<()> {
|
|||
*zebra_test::vectors::SAPLING_TREESTATE_MAINNET_419201_STRING
|
||||
);
|
||||
|
||||
// Call `z_getsubtreesbyindex` separately for
|
||||
|
||||
// ... Sapling.
|
||||
let mut subtrees = rpc_client
|
||||
.get_subtree_roots(GetSubtreeRootsArg {
|
||||
start_index: 0u32,
|
||||
shielded_protocol: ShieldedProtocol::Sapling.into(),
|
||||
max_entries: 2u32,
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
let mut counter = 0;
|
||||
while let Some(subtree) = subtrees.message().await? {
|
||||
match counter {
|
||||
0 => {
|
||||
assert_eq!(
|
||||
subtree.root_hash,
|
||||
hex!("754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13")
|
||||
);
|
||||
assert_eq!(subtree.completing_block_height, 558822u64);
|
||||
}
|
||||
1 => {
|
||||
assert_eq!(
|
||||
subtree.root_hash,
|
||||
hex!("03654c3eacbb9b93e122cf6d77b606eae29610f4f38a477985368197fd68e02d")
|
||||
);
|
||||
assert_eq!(subtree.completing_block_height, 670209u64);
|
||||
}
|
||||
_ => {
|
||||
panic!("The response from the `z_getsubtreesbyindex` RPC contains a wrong number of Sapling subtrees.")
|
||||
}
|
||||
}
|
||||
counter += 1;
|
||||
}
|
||||
assert_eq!(counter, 2);
|
||||
|
||||
// ... Orchard.
|
||||
let mut subtrees = rpc_client
|
||||
.get_subtree_roots(GetSubtreeRootsArg {
|
||||
start_index: 0u32,
|
||||
shielded_protocol: ShieldedProtocol::Orchard.into(),
|
||||
max_entries: 2u32,
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
let mut counter = 0;
|
||||
while let Some(subtree) = subtrees.message().await? {
|
||||
match counter {
|
||||
0 => {
|
||||
assert_eq!(
|
||||
subtree.root_hash,
|
||||
hex!("d4e323b3ae0cabfb6be4087fec8c66d9a9bbfc354bf1d9588b6620448182063b")
|
||||
);
|
||||
assert_eq!(subtree.completing_block_height, 1707429u64);
|
||||
}
|
||||
1 => {
|
||||
assert_eq!(
|
||||
subtree.root_hash,
|
||||
hex!("8c47d0ca43f323ac573ee57c90af4ced484682827248ca5f3eead95eb6415a14")
|
||||
);
|
||||
assert_eq!(subtree.completing_block_height, 1708132u64);
|
||||
}
|
||||
_ => {
|
||||
panic!("The response from the `z_getsubtreesbyindex` RPC contains a wrong number of Orchard subtrees.")
|
||||
}
|
||||
}
|
||||
counter += 1;
|
||||
}
|
||||
assert_eq!(counter, 2);
|
||||
|
||||
// Call `GetAddressUtxos` with the ZF funding stream address that will always have utxos
|
||||
let utxos = rpc_client
|
||||
.get_address_utxos(GetAddressUtxosArg {
|
||||
|
|
Loading…
Reference in New Issue