Reorganize Sapling and Orchard note commitment tree sizes in CompactBlock.
We move thes fields out into a separate BlockMetadata struct to ensure that future additions to block metadata are structurally separated from future additions to block data.
This commit is contained in:
parent
547634e210
commit
ba709177d3
|
@ -10,20 +10,27 @@ option swift_prefix = "";
|
|||
// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value.
|
||||
// bytes fields of hashes are in canonical little-endian format.
|
||||
|
||||
// BlockMetadata represents information about a block that may not be
|
||||
// represented directly in the block data, but is instead derived from chain
|
||||
// data or other external sources.
|
||||
message BlockMetadata {
|
||||
uint32 saplingCommitmentTreeSize = 1; // the size of the Sapling note commitment tree as of the end of this block
|
||||
uint32 orchardCommitmentTreeSize = 2; // the size of the Orchard note commitment tree as of the end of this block
|
||||
}
|
||||
|
||||
// CompactBlock is a packaging of ONLY the data from a block that's needed to:
|
||||
// 1. Detect a payment to your shielded Sapling address
|
||||
// 2. Detect a spend of your shielded Sapling notes
|
||||
// 3. Update your witnesses to generate new Sapling spend proofs.
|
||||
message CompactBlock {
|
||||
uint32 protoVersion = 1; // the version of this wire format, for storage
|
||||
uint64 height = 2; // the height of this block
|
||||
bytes hash = 3; // the ID (hash) of this block, same as in block explorers
|
||||
bytes prevHash = 4; // the ID (hash) of this block's predecessor
|
||||
uint32 time = 5; // Unix epoch time when the block was mined
|
||||
bytes header = 6; // (hash, prevHash, and time) OR (full header)
|
||||
repeated CompactTx vtx = 7; // zero or more compact transactions from this block
|
||||
uint32 saplingCommitmentTreeSize = 8; // the size of the Sapling note commitment tree as of the end of this block
|
||||
uint32 orchardCommitmentTreeSize = 9; // the size of the Orchard note commitment tree as of the end of this block
|
||||
uint32 protoVersion = 1; // the version of this wire format, for storage
|
||||
uint64 height = 2; // the height of this block
|
||||
bytes hash = 3; // the ID (hash) of this block, same as in block explorers
|
||||
bytes prevHash = 4; // the ID (hash) of this block's predecessor
|
||||
uint32 time = 5; // Unix epoch time when the block was mined
|
||||
bytes header = 6; // (hash, prevHash, and time) OR (full header)
|
||||
repeated CompactTx vtx = 7; // zero or more compact transactions from this block
|
||||
BlockMetadata blockMetadata = 8; // information about this block derived from the chain or other sources
|
||||
}
|
||||
|
||||
// CompactTx contains the minimum information for a wallet to know if this transaction
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
/// BlockMetadata represents information about a block that may not be
|
||||
/// represented directly in the block data, but is instead derived from chain
|
||||
/// data or other external sources.
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct BlockMetadata {
|
||||
/// the size of the Sapling note commitment tree as of the end of this block
|
||||
#[prost(uint32, tag = "1")]
|
||||
pub sapling_commitment_tree_size: u32,
|
||||
/// the size of the Orchard note commitment tree as of the end of this block
|
||||
#[prost(uint32, tag = "2")]
|
||||
pub orchard_commitment_tree_size: u32,
|
||||
}
|
||||
/// CompactBlock is a packaging of ONLY the data from a block that's needed to:
|
||||
/// 1. Detect a payment to your shielded Sapling address
|
||||
/// 2. Detect a spend of your shielded Sapling notes
|
||||
|
@ -26,12 +39,9 @@ pub struct CompactBlock {
|
|||
/// zero or more compact transactions from this block
|
||||
#[prost(message, repeated, tag = "7")]
|
||||
pub vtx: ::prost::alloc::vec::Vec<CompactTx>,
|
||||
/// the size of the Sapling note commitment tree as of the end of this block
|
||||
#[prost(uint32, tag = "8")]
|
||||
pub sapling_commitment_tree_size: u32,
|
||||
/// the size of the Orchard note commitment tree as of the end of this block
|
||||
#[prost(uint32, tag = "9")]
|
||||
pub orchard_commitment_tree_size: u32,
|
||||
/// information about this block derived from the chain or other sources
|
||||
#[prost(message, optional, tag = "8")]
|
||||
pub block_metadata: ::core::option::Option<BlockMetadata>,
|
||||
}
|
||||
/// CompactTx contains the minimum information for a wallet to know if this transaction
|
||||
/// is relevant to it (either pays to it or spends from it) via shielded elements
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
/// BlockMetadata represents information about a block that may not be
|
||||
/// represented directly in the block data, but is instead derived from chain
|
||||
/// data or other external sources.
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct BlockMetadata {
|
||||
/// the size of the Sapling note commitment tree as of the end of this block
|
||||
#[prost(uint32, tag = "1")]
|
||||
pub sapling_commitment_tree_size: u32,
|
||||
/// the size of the Orchard note commitment tree as of the end of this block
|
||||
#[prost(uint32, tag = "2")]
|
||||
pub orchard_commitment_tree_size: u32,
|
||||
}
|
||||
/// A BlockID message contains identifiers to select a block: a height or a
|
||||
/// hash. Specification by hash is not implemented, but may be in the future.
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
|
|
|
@ -218,16 +218,21 @@ pub(crate) fn scan_block_with_runner<
|
|||
// to use it. `block.sapling_commitment_tree_size` is expected to be correct as of the end of
|
||||
// the block, and we can't have a note of ours in a block with no outputs so treating the zero
|
||||
// default value from the protobuf as `None` is always correct.
|
||||
let mut sapling_tree_position = if block.sapling_commitment_tree_size == 0 {
|
||||
initial_commitment_tree_meta.map(|m| (m.sapling_tree_size() + 1).into())
|
||||
} else {
|
||||
let end_position_exclusive = Position::from(u64::from(block.sapling_commitment_tree_size));
|
||||
let mut sapling_tree_position = if let Some(sapling_tree_size) = block
|
||||
.block_metadata
|
||||
.as_ref()
|
||||
.map(|m| m.sapling_commitment_tree_size)
|
||||
.filter(|s| *s != 0)
|
||||
{
|
||||
let end_position_exclusive = Position::from(u64::from(sapling_tree_size));
|
||||
let output_count = block
|
||||
.vtx
|
||||
.iter()
|
||||
.map(|tx| u64::try_from(tx.outputs.len()).unwrap())
|
||||
.sum();
|
||||
Some(end_position_exclusive - output_count)
|
||||
} else {
|
||||
initial_commitment_tree_meta.map(|m| (m.sapling_tree_size() + 1).into())
|
||||
};
|
||||
|
||||
for tx in block.vtx.into_iter() {
|
||||
|
@ -404,11 +409,10 @@ pub(crate) fn scan_block_with_runner<
|
|||
block_hash,
|
||||
block_time: block.time,
|
||||
transactions: wtxs,
|
||||
sapling_commitment_tree_size: if block.sapling_commitment_tree_size == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(block.sapling_commitment_tree_size)
|
||||
},
|
||||
sapling_commitment_tree_size: block
|
||||
.block_metadata
|
||||
.map(|m| m.sapling_commitment_tree_size)
|
||||
.filter(|s| *s != 0),
|
||||
sapling_commitments: sapling_note_commitments,
|
||||
})
|
||||
}
|
||||
|
@ -439,7 +443,7 @@ mod tests {
|
|||
use crate::{
|
||||
data_api::chain::CommitmentTreeMeta,
|
||||
proto::compact_formats::{
|
||||
CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
||||
BlockMetadata, CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
||||
},
|
||||
scan::BatchRunner,
|
||||
};
|
||||
|
@ -547,8 +551,11 @@ mod tests {
|
|||
cb.vtx.push(tx);
|
||||
}
|
||||
|
||||
cb.sapling_commitment_tree_size = initial_sapling_tree_size
|
||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>();
|
||||
cb.block_metadata = Some(BlockMetadata {
|
||||
sapling_commitment_tree_size: initial_sapling_tree_size
|
||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
cb
|
||||
}
|
||||
|
|
|
@ -964,7 +964,7 @@ mod tests {
|
|||
data_api::{WalletRead, WalletWrite},
|
||||
keys::{sapling, UnifiedFullViewingKey},
|
||||
proto::compact_formats::{
|
||||
CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
||||
BlockMetadata, CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1109,8 +1109,11 @@ mod tests {
|
|||
};
|
||||
cb.prev_hash.extend_from_slice(&prev_hash.0);
|
||||
cb.vtx.push(ctx);
|
||||
cb.sapling_commitment_tree_size = initial_sapling_tree_size
|
||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>();
|
||||
cb.block_metadata = Some(BlockMetadata {
|
||||
sapling_commitment_tree_size: initial_sapling_tree_size
|
||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>(),
|
||||
..Default::default()
|
||||
});
|
||||
(cb, note.nf(&dfvk.fvk().vk.nk, 0))
|
||||
}
|
||||
|
||||
|
@ -1197,8 +1200,11 @@ mod tests {
|
|||
};
|
||||
cb.prev_hash.extend_from_slice(&prev_hash.0);
|
||||
cb.vtx.push(ctx);
|
||||
cb.sapling_commitment_tree_size = initial_sapling_tree_size
|
||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>();
|
||||
cb.block_metadata = Some(BlockMetadata {
|
||||
sapling_commitment_tree_size: initial_sapling_tree_size
|
||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>(),
|
||||
..Default::default()
|
||||
});
|
||||
cb
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue