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.
|
// 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.
|
// 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:
|
// CompactBlock is a packaging of ONLY the data from a block that's needed to:
|
||||||
// 1. Detect a payment to your shielded Sapling address
|
// 1. Detect a payment to your shielded Sapling address
|
||||||
// 2. Detect a spend of your shielded Sapling notes
|
// 2. Detect a spend of your shielded Sapling notes
|
||||||
// 3. Update your witnesses to generate new Sapling spend proofs.
|
// 3. Update your witnesses to generate new Sapling spend proofs.
|
||||||
message CompactBlock {
|
message CompactBlock {
|
||||||
uint32 protoVersion = 1; // the version of this wire format, for storage
|
uint32 protoVersion = 1; // the version of this wire format, for storage
|
||||||
uint64 height = 2; // the height of this block
|
uint64 height = 2; // the height of this block
|
||||||
bytes hash = 3; // the ID (hash) of this block, same as in block explorers
|
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
|
bytes prevHash = 4; // the ID (hash) of this block's predecessor
|
||||||
uint32 time = 5; // Unix epoch time when the block was mined
|
uint32 time = 5; // Unix epoch time when the block was mined
|
||||||
bytes header = 6; // (hash, prevHash, and time) OR (full header)
|
bytes header = 6; // (hash, prevHash, and time) OR (full header)
|
||||||
repeated CompactTx vtx = 7; // zero or more compact transactions from this block
|
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
|
BlockMetadata blockMetadata = 8; // information about this block derived from the chain or other sources
|
||||||
uint32 orchardCommitmentTreeSize = 9; // the size of the Orchard note commitment tree as of the end of this block
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompactTx contains the minimum information for a wallet to know if this transaction
|
// 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:
|
/// CompactBlock is a packaging of ONLY the data from a block that's needed to:
|
||||||
/// 1. Detect a payment to your shielded Sapling address
|
/// 1. Detect a payment to your shielded Sapling address
|
||||||
/// 2. Detect a spend of your shielded Sapling notes
|
/// 2. Detect a spend of your shielded Sapling notes
|
||||||
|
@ -26,12 +39,9 @@ pub struct CompactBlock {
|
||||||
/// zero or more compact transactions from this block
|
/// zero or more compact transactions from this block
|
||||||
#[prost(message, repeated, tag = "7")]
|
#[prost(message, repeated, tag = "7")]
|
||||||
pub vtx: ::prost::alloc::vec::Vec<CompactTx>,
|
pub vtx: ::prost::alloc::vec::Vec<CompactTx>,
|
||||||
/// the size of the Sapling note commitment tree as of the end of this block
|
/// information about this block derived from the chain or other sources
|
||||||
#[prost(uint32, tag = "8")]
|
#[prost(message, optional, tag = "8")]
|
||||||
pub sapling_commitment_tree_size: u32,
|
pub block_metadata: ::core::option::Option<BlockMetadata>,
|
||||||
/// 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,
|
|
||||||
}
|
}
|
||||||
/// CompactTx contains the minimum information for a wallet to know if this transaction
|
/// 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
|
/// 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
|
/// 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.
|
/// hash. Specification by hash is not implemented, but may be in the future.
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[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
|
// 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
|
// 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.
|
// default value from the protobuf as `None` is always correct.
|
||||||
let mut sapling_tree_position = if block.sapling_commitment_tree_size == 0 {
|
let mut sapling_tree_position = if let Some(sapling_tree_size) = block
|
||||||
initial_commitment_tree_meta.map(|m| (m.sapling_tree_size() + 1).into())
|
.block_metadata
|
||||||
} else {
|
.as_ref()
|
||||||
let end_position_exclusive = Position::from(u64::from(block.sapling_commitment_tree_size));
|
.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
|
let output_count = block
|
||||||
.vtx
|
.vtx
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tx| u64::try_from(tx.outputs.len()).unwrap())
|
.map(|tx| u64::try_from(tx.outputs.len()).unwrap())
|
||||||
.sum();
|
.sum();
|
||||||
Some(end_position_exclusive - output_count)
|
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() {
|
for tx in block.vtx.into_iter() {
|
||||||
|
@ -404,11 +409,10 @@ pub(crate) fn scan_block_with_runner<
|
||||||
block_hash,
|
block_hash,
|
||||||
block_time: block.time,
|
block_time: block.time,
|
||||||
transactions: wtxs,
|
transactions: wtxs,
|
||||||
sapling_commitment_tree_size: if block.sapling_commitment_tree_size == 0 {
|
sapling_commitment_tree_size: block
|
||||||
None
|
.block_metadata
|
||||||
} else {
|
.map(|m| m.sapling_commitment_tree_size)
|
||||||
Some(block.sapling_commitment_tree_size)
|
.filter(|s| *s != 0),
|
||||||
},
|
|
||||||
sapling_commitments: sapling_note_commitments,
|
sapling_commitments: sapling_note_commitments,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -439,7 +443,7 @@ mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
data_api::chain::CommitmentTreeMeta,
|
data_api::chain::CommitmentTreeMeta,
|
||||||
proto::compact_formats::{
|
proto::compact_formats::{
|
||||||
CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
BlockMetadata, CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
||||||
},
|
},
|
||||||
scan::BatchRunner,
|
scan::BatchRunner,
|
||||||
};
|
};
|
||||||
|
@ -547,8 +551,11 @@ mod tests {
|
||||||
cb.vtx.push(tx);
|
cb.vtx.push(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
cb.sapling_commitment_tree_size = initial_sapling_tree_size
|
cb.block_metadata = Some(BlockMetadata {
|
||||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>();
|
sapling_commitment_tree_size: initial_sapling_tree_size
|
||||||
|
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
cb
|
cb
|
||||||
}
|
}
|
||||||
|
|
|
@ -964,7 +964,7 @@ mod tests {
|
||||||
data_api::{WalletRead, WalletWrite},
|
data_api::{WalletRead, WalletWrite},
|
||||||
keys::{sapling, UnifiedFullViewingKey},
|
keys::{sapling, UnifiedFullViewingKey},
|
||||||
proto::compact_formats::{
|
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.prev_hash.extend_from_slice(&prev_hash.0);
|
||||||
cb.vtx.push(ctx);
|
cb.vtx.push(ctx);
|
||||||
cb.sapling_commitment_tree_size = initial_sapling_tree_size
|
cb.block_metadata = Some(BlockMetadata {
|
||||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>();
|
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))
|
(cb, note.nf(&dfvk.fvk().vk.nk, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1197,8 +1200,11 @@ mod tests {
|
||||||
};
|
};
|
||||||
cb.prev_hash.extend_from_slice(&prev_hash.0);
|
cb.prev_hash.extend_from_slice(&prev_hash.0);
|
||||||
cb.vtx.push(ctx);
|
cb.vtx.push(ctx);
|
||||||
cb.sapling_commitment_tree_size = initial_sapling_tree_size
|
cb.block_metadata = Some(BlockMetadata {
|
||||||
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>();
|
sapling_commitment_tree_size: initial_sapling_tree_size
|
||||||
|
+ cb.vtx.iter().map(|tx| tx.outputs.len() as u32).sum::<u32>(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
cb
|
cb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue