Skip to content

Commit

Permalink
[feature] hyperledger-iroha#2227: adjust public blockchain validators…
Browse files Browse the repository at this point in the history
… to account for (un)registering an asset

Signed-off-by: Artemii Gerasimovich <gerasimovich@soramitsu.co.jp>
  • Loading branch information
Artemii Gerasimovich committed Jun 8, 2022
1 parent 54c9d0d commit 7c0bfa4
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 95 deletions.
183 changes: 121 additions & 62 deletions permissions_validators/src/public_blockchain/burn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use iroha_data_model::asset::DefinitionId;
use super::*;

declare_token!(
/// Can burn asset with the corresponding asset definition.
/// Can burn and unregister asset with the corresponding asset definition.
CanBurnAssetWithDefinition {
/// Asset definition id.
asset_definition_id ("asset_definition_id"): DefinitionId,
Expand Down Expand Up @@ -35,24 +35,49 @@ impl<W: WorldTrait> IsAllowed<W, Instruction> for OnlyAssetsCreatedByThisAccount
instruction: &Instruction,
wsv: &WorldStateView<W>,
) -> Result<(), DenialReason> {
let burn_box = if let Instruction::Burn(burn) = instruction {
burn
} else {
return Ok(());
};
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = try_into_or_exit!(destination_id);
let registered_by_signer_account = wsv
.asset_definition_entry(&asset_id.definition_id)
.map(|asset_definition_entry| asset_definition_entry.registered_by() == authority)
.unwrap_or(false);
if !registered_by_signer_account {
return Err("Can't burn assets registered by other accounts.".to_owned());
match instruction {
Instruction::Unregister(unregister) => {
if let IdBox::AssetId(asset_id) = unregister
.object_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?
{
let registered_by_signer_account = wsv
.asset_definition_entry(&asset_id.definition_id)
.map(|asset_definition_entry| {
asset_definition_entry.registered_by() == authority
})
.unwrap_or(false);
if !registered_by_signer_account {
return Err(
"Can't unregister assets with definitions registered by other accounts.".to_owned()
);
}
}
Ok(())
}
Instruction::Burn(burn_box) => {
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = try_into_or_exit!(destination_id);
let registered_by_signer_account = wsv
.asset_definition_entry(&asset_id.definition_id)
.map(|asset_definition_entry| {
asset_definition_entry.registered_by() == authority
})
.unwrap_or(false);
if !registered_by_signer_account {
return Err(
"Can't burn assets with definitions registered by other accounts."
.to_owned(),
);
}
Ok(())
}
_ => Ok(()),
}
Ok(())
}
}

Expand All @@ -70,22 +95,33 @@ impl<W: WorldTrait> HasToken<W> for GrantedByAssetCreator {
instruction: &Instruction,
wsv: &WorldStateView<W>,
) -> Result<PermissionToken, String> {
let burn_box = if let Instruction::Burn(burn) = instruction {
burn
} else {
return Err("Instruction is not burn.".to_owned());
};
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = if let Ok(dest_id) = destination_id.try_into() {
dest_id
} else {
return Err("Destination is not an Asset.".to_owned());
};

Ok(CanBurnAssetWithDefinition::new(asset_id.definition_id).into())
match instruction {
Instruction::Unregister(unregister) => {
if let IdBox::AssetId(asset_id) = unregister
.object_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?
{
Ok(CanBurnAssetWithDefinition::new(asset_id.definition_id).into())
} else {
Err("Instruction is not unregister asset".to_owned())
}
}
Instruction::Burn(burn_box) => {
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = if let Ok(dest_id) = destination_id.try_into() {
dest_id
} else {
return Err("Destination is not an Asset.".to_owned());
};

Ok(CanBurnAssetWithDefinition::new(asset_id.definition_id).into())
}
_ => Err("Instruction is not burn or unregister asset.".to_owned()),
}
}
}

Expand Down Expand Up @@ -122,20 +158,32 @@ impl<W: WorldTrait> IsAllowed<W, Instruction> for OnlyOwnedAssets {
instruction: &Instruction,
wsv: &WorldStateView<W>,
) -> Result<(), DenialReason> {
let burn_box = if let Instruction::Burn(burn) = instruction {
burn
} else {
return Ok(());
};
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = try_into_or_exit!(destination_id);
if &asset_id.account_id != authority {
return Err("Can't burn assets from another account.".to_owned());
match instruction {
Instruction::Unregister(unregister) => {
if let IdBox::AssetId(asset_id) = unregister
.object_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?
{
if &asset_id.account_id != authority {
return Err("Can't unregister assets from another account.".to_owned());
}
}
Ok(())
}
Instruction::Burn(burn_box) => {
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = try_into_or_exit!(destination_id);
if &asset_id.account_id != authority {
return Err("Can't burn assets from another account.".to_owned());
}
Ok(())
}
_ => Ok(()),
}
Ok(())
}
}

Expand All @@ -152,21 +200,32 @@ impl<W: WorldTrait> HasToken<W> for GrantedByAssetOwner {
instruction: &Instruction,
wsv: &WorldStateView<W>,
) -> Result<PermissionToken, String> {
let burn_box = if let Instruction::Burn(burn_box) = instruction {
burn_box
} else {
return Err("Instruction is not burn.".to_owned());
};
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let destination_id: AssetId = if let Ok(dest_id) = destination_id.try_into() {
dest_id
} else {
return Err("Source id is not an AssetId.".to_owned());
};
Ok(CanBurnUserAssets::new(destination_id).into())
match instruction {
Instruction::Unregister(unregister) => {
if let IdBox::AssetId(asset_id) = unregister
.object_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?
{
Ok(CanBurnUserAssets::new(asset_id).into())
} else {
Err("Instruction is not unregister asset.".to_owned())
}
}
Instruction::Burn(burn_box) => {
let destination_id = burn_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let destination_id: AssetId = if let Ok(dest_id) = destination_id.try_into() {
dest_id
} else {
return Err("Source id is not an AssetId.".to_owned());
};
Ok(CanBurnUserAssets::new(destination_id).into())
}
_ => Err("Instruction is not burn or unregister asset.".to_owned()),
}
}
}

Expand Down
104 changes: 71 additions & 33 deletions permissions_validators/src/public_blockchain/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use iroha_data_model::asset::DefinitionId;
use super::*;

declare_token!(
/// Can mint asset with the corresponding asset definition.
/// Can register and mint asset with the corresponding asset definition.
CanMintUserAssetDefinitions {
/// Asset definition id
asset_definition_id ("asset_definition_id"): DefinitionId,
Expand All @@ -25,24 +25,51 @@ impl<W: WorldTrait> IsAllowed<W, Instruction> for OnlyAssetsCreatedByThisAccount
instruction: &Instruction,
wsv: &WorldStateView<W>,
) -> Result<(), DenialReason> {
let mint_box = if let Instruction::Mint(mint) = instruction {
mint
} else {
return Ok(());
};
let destination_id = mint_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = try_into_or_exit!(destination_id);
let registered_by_signer_account = wsv
.asset_definition_entry(&asset_id.definition_id)
.map(|asset_definition_entry| asset_definition_entry.registered_by() == authority)
.unwrap_or(false);
if !registered_by_signer_account {
return Err("Can't mint assets registered by other accounts.".to_owned());
match instruction {
Instruction::Register(register) => {
if let RegistrableBox::Asset(asset) = register
.object
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?
{
let registered_by_signer_account = wsv
.asset_definition_entry(&asset.id().definition_id)
.map(|asset_definition_entry| {
asset_definition_entry.registered_by() == authority
})
.unwrap_or(false);

if !registered_by_signer_account {
return Err(
"Can't register assets with definitions registered by other accounts."
.to_owned(),
);
}
}
Ok(())
}
Instruction::Mint(mint_box) => {
let destination_id = mint_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = try_into_or_exit!(destination_id);
let registered_by_signer_account = wsv
.asset_definition_entry(&asset_id.definition_id)
.map(|asset_definition_entry| {
asset_definition_entry.registered_by() == authority
})
.unwrap_or(false);
if !registered_by_signer_account {
return Err(
"Can't mint assets with definitions registered by other accounts."
.to_owned(),
);
}
Ok(())
}
_ => Ok(()),
}
Ok(())
}
}

Expand All @@ -60,21 +87,32 @@ impl<W: WorldTrait> HasToken<W> for GrantedByAssetCreator {
instruction: &Instruction,
wsv: &WorldStateView<W>,
) -> Result<PermissionToken, String> {
let mint_box = if let Instruction::Mint(mint) = instruction {
mint
} else {
return Err("Instruction is not mint.".to_owned());
};
let destination_id = mint_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = if let Ok(dest_id) = destination_id.try_into() {
dest_id
} else {
return Err("Destination is not an Asset.".to_owned());
};
Ok(CanMintUserAssetDefinitions::new(asset_id.definition_id).into())
match instruction {
Instruction::Register(register) => {
if let RegistrableBox::Asset(asset) = register
.object
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?
{
Ok(CanMintUserAssetDefinitions::new(asset.id().definition_id.clone()).into())
} else {
Err("Instruction is not register asset".to_owned())
}
}
Instruction::Mint(mint_box) => {
let destination_id = mint_box
.destination_id
.evaluate(wsv, &Context::new())
.map_err(|e| e.to_string())?;
let asset_id: AssetId = if let Ok(dest_id) = destination_id.try_into() {
dest_id
} else {
return Err("Destination is not an Asset.".to_owned());
};
Ok(CanMintUserAssetDefinitions::new(asset_id.definition_id).into())
}
_ => Err("Instruction is not mint or register asset.".to_owned()),
}
}
}

Expand Down

0 comments on commit 7c0bfa4

Please sign in to comment.