From c4d0c32d319367fa458955738c9b0f3564fb063d Mon Sep 17 00:00:00 2001 From: ar Date: Wed, 13 Nov 2024 20:21:33 -0500 Subject: [PATCH] wip2 --- zebra-chain/src/orchard_zsa/asset_state.rs | 7 ++- zebra-consensus/src/block.rs | 9 ++-- zebra-state/src/request.rs | 24 +--------- zebra-state/src/service/check/issuance.rs | 51 +++++++++------------- 4 files changed, 32 insertions(+), 59 deletions(-) diff --git a/zebra-chain/src/orchard_zsa/asset_state.rs b/zebra-chain/src/orchard_zsa/asset_state.rs index 242a8019722..034bad7e369 100644 --- a/zebra-chain/src/orchard_zsa/asset_state.rs +++ b/zebra-chain/src/orchard_zsa/asset_state.rs @@ -204,6 +204,11 @@ impl AssetStateChange { self.is_finalized |= change.is_finalized; self.supply_change.add(change.supply_change) } + + /// Returns true if the AssetStateChange is for an asset burn. + pub fn is_burn(&self) -> bool { + matches!(self.supply_change, SupplyChange::Burn(_)) + } } /// An `issued_asset` map @@ -240,7 +245,7 @@ impl IntoIterator for IssuedAssets { } /// A map of changes to apply to the issued assets map. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct IssuedAssetsChange(HashMap); impl IssuedAssetsChange { diff --git a/zebra-consensus/src/block.rs b/zebra-consensus/src/block.rs index 31fe5a24e9d..eef12c42369 100644 --- a/zebra-consensus/src/block.rs +++ b/zebra-consensus/src/block.rs @@ -315,7 +315,9 @@ where let new_outputs = Arc::into_inner(known_utxos) .expect("all verification tasks using known_utxos are complete"); - let (burns, issuance) = IssuedAssetsChange::from_transactions(&block.transactions); + let issued_assets_change = IssuedAssetsChange::from_transactions(&block.transactions) + .ok_or("invalid asset issuance or burns")?; + let prepared_block = zs::SemanticallyVerifiedBlock { block, hash, @@ -323,10 +325,7 @@ where new_outputs, transaction_hashes, deferred_balance: Some(expected_deferred_amount), - issued_assets_changes: IssuedAssetsOrChanges::BurnAndIssuanceChanges { - burns, - issuance, - }, + issued_assets_change: Some(issued_assets_change), }; // Return early for proposal requests when getblocktemplate-rpcs feature is enabled diff --git a/zebra-state/src/request.rs b/zebra-state/src/request.rs index 92a9d162594..89d20759161 100644 --- a/zebra-state/src/request.rs +++ b/zebra-state/src/request.rs @@ -166,7 +166,7 @@ pub struct SemanticallyVerifiedBlock { pub deferred_balance: Option>, /// A map of burns to be applied to the issued assets map. // TODO: Reference ZIP. - pub issued_assets_changes: IssuedAssetsOrChanges, + pub issued_assets_change: Option, } /// A block ready to be committed directly to the finalized state with @@ -317,26 +317,6 @@ pub enum IssuedAssetsOrChanges { /// A map of changes to apply to the issued assets map. Change(IssuedAssetsChange), - - /// A map of changes from burns and issuance to apply to the issued assets map. - BurnAndIssuanceChanges { - /// A map of changes from burns to apply to the issued assets map. - burns: IssuedAssetsChange, - /// A map of changes from issuance to apply to the issued assets map. - issuance: IssuedAssetsChange, - }, -} - -impl IssuedAssetsOrChanges { - /// Combines fields in the `BurnAndIssuanceChanges` variant then returns a `Change` variant, or - /// returns self unmodified. - pub fn combine(self) -> Self { - let Self::BurnAndIssuanceChanges { burns, issuance } = self else { - return self; - }; - - Self::Change(burns + issuance) - } } impl From for IssuedAssetsOrChanges { @@ -369,7 +349,7 @@ impl FinalizedBlock { transaction_hashes: block.transaction_hashes, treestate, deferred_balance: block.deferred_balance, - issued_assets: block.issued_assets_changes, + issued_assets: block.issued_assets_change, } } } diff --git a/zebra-state/src/service/check/issuance.rs b/zebra-state/src/service/check/issuance.rs index 5454e85290f..daf7635e68a 100644 --- a/zebra-state/src/service/check/issuance.rs +++ b/zebra-state/src/service/check/issuance.rs @@ -4,7 +4,7 @@ use std::{collections::HashMap, sync::Arc}; use zebra_chain::orchard_zsa::IssuedAssets; -use crate::{IssuedAssetsOrChanges, SemanticallyVerifiedBlock, ValidateContextError, ZebraDb}; +use crate::{SemanticallyVerifiedBlock, ValidateContextError, ZebraDb}; use super::Chain; @@ -13,45 +13,34 @@ pub fn valid_burns_and_issuance( parent_chain: &Arc, semantically_verified: &SemanticallyVerifiedBlock, ) -> Result { - let IssuedAssetsOrChanges::BurnAndIssuanceChanges { burns, issuance } = - semantically_verified.issued_assets_changes.clone() - else { - panic!("unexpected variant in semantically verified block") + let Some(issued_assets_change) = semantically_verified.issued_assets_change.clone() else { + return Ok(IssuedAssets::default()); }; let mut issued_assets = HashMap::new(); - for (asset_base, burn_change) in burns.clone() { - // TODO: Move this to a read fn. - let updated_asset_state = parent_chain - .issued_asset(&asset_base) - .or_else(|| finalized_state.issued_asset(&asset_base)) - .ok_or(ValidateContextError::InvalidBurn)? - .apply_change(burn_change) - .ok_or(ValidateContextError::InvalidBurn)?; - - issued_assets - .insert(asset_base, updated_asset_state) - .expect("transactions must have only one burn item per asset base"); - } - - for (asset_base, issuance_change) in issuance.clone() { - // TODO: Move this to a read fn. - let Some(asset_state) = issued_assets + for (asset_base, change) in issued_assets_change { + let asset_state = issued_assets .get(&asset_base) .copied() .or_else(|| parent_chain.issued_asset(&asset_base)) - .or_else(|| finalized_state.issued_asset(&asset_base)) - else { - continue; - }; + .or_else(|| finalized_state.issued_asset(&asset_base)); - let _ = issued_assets.insert( - asset_base, + let updated_asset_state = if change.is_burn() { asset_state - .apply_change(issuance_change) - .ok_or(ValidateContextError::InvalidIssuance)?, - ); + .ok_or(ValidateContextError::InvalidBurn)? + .apply_change(change) + .ok_or(ValidateContextError::InvalidBurn)? + } else { + asset_state + .unwrap_or_default() + .apply_change(change) + .ok_or(ValidateContextError::InvalidIssuance)? + }; + + issued_assets + .insert(asset_base, updated_asset_state) + .expect("transactions must have only one burn item per asset base"); } Ok(issued_assets.into())