1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
use std::{ collections::BTreeMap, convert::{TryFrom, TryInto}, mem, }; use casper_execution_engine::shared::account::{Account, ActionThresholds, AssociatedKeys}; use casper_types::account::{AccountHash, Weight}; use super::NamedKeyMap; use crate::engine_server::{ mappings::{self, ParsingError}, state::{self, Account_AssociatedKey, NamedKey}, }; impl From<Account> for state::Account { fn from(mut account: Account) -> Self { let mut pb_account = state::Account::new(); pb_account.public_key = account.account_hash().as_bytes().to_vec(); let named_keys = mem::replace(account.named_keys_mut(), BTreeMap::new()); let pb_named_keys: Vec<NamedKey> = NamedKeyMap::new(named_keys).into(); pb_account.set_named_keys(pb_named_keys.into()); pb_account.set_main_purse(account.main_purse().into()); let associated_keys: Vec<Account_AssociatedKey> = account.get_associated_keys().map(Into::into).collect(); pb_account.set_associated_keys(associated_keys.into()); { let deployment = u32::from(account.action_thresholds().deployment().value()); let key_management = u32::from(account.action_thresholds().key_management().value()); let pb_action_thresholds = pb_account.mut_action_thresholds(); pb_action_thresholds.set_deployment_threshold(deployment); pb_action_thresholds.set_key_management_threshold(key_management) } pb_account } } impl TryFrom<state::Account> for Account { type Error = ParsingError; fn try_from(pb_account: state::Account) -> Result<Self, Self::Error> { let account_hash = mappings::vec_to_array(pb_account.public_key, "Protobuf Account::AccountHash")?; let named_keys: NamedKeyMap = pb_account.named_keys.into_vec().try_into()?; let main_purse = { let pb_uref = pb_account .main_purse .into_option() .ok_or_else(|| ParsingError::from("Protobuf Account missing MainPurse field"))?; pb_uref.try_into()? }; let associated_keys = { let mut associated_keys = AssociatedKeys::default(); for pb_associated_key in pb_account.associated_keys.into_vec() { let (key, weight) = pb_associated_key.try_into()?; associated_keys.add_key(key, weight).map_err(|error| { ParsingError(format!( "Error parsing Protobuf Account::AssociatedKeys: {:?}", error )) })?; } associated_keys }; let action_thresholds = { let pb_action_thresholds = pb_account.action_thresholds.into_option().ok_or_else(|| { ParsingError::from("Protobuf Account missing ActionThresholds field") })?; ActionThresholds::new( weight_from( pb_action_thresholds.deployment_threshold, "Protobuf DeploymentThreshold", )?, weight_from( pb_action_thresholds.key_management_threshold, "Protobuf KeyManagementThreshold", )?, ) .map_err(ParsingError::from)? }; let account = Account::new( AccountHash::new(account_hash), named_keys.into_inner(), main_purse, associated_keys, action_thresholds, ); Ok(account) } } impl From<(&AccountHash, &Weight)> for Account_AssociatedKey { fn from((account_hash, weight): (&AccountHash, &Weight)) -> Self { let mut pb_associated_key = Account_AssociatedKey::new(); pb_associated_key.public_key = account_hash.as_bytes().to_vec(); pb_associated_key.set_weight(weight.value().into()); pb_associated_key } } impl TryFrom<Account_AssociatedKey> for (AccountHash, Weight) { type Error = ParsingError; fn try_from(pb_associated_key: Account_AssociatedKey) -> Result<Self, Self::Error> { let account_hash = AccountHash::new(mappings::vec_to_array( pb_associated_key.public_key, "Protobuf Account::AssociatedKey", )?); let weight = weight_from(pb_associated_key.weight, "Protobuf AssociatedKey::Weight")?; Ok((account_hash, weight)) } } fn weight_from(value: u32, value_name: &str) -> Result<Weight, ParsingError> { let weight = u8::try_from(value).map_err(|_| { ParsingError(format!( "Unable to convert {} to u8 while parsing {}", value, value_name )) })?; Ok(Weight::new(weight)) } #[cfg(test)] mod tests { use proptest::proptest; use casper_execution_engine::shared::account::gens; use super::*; use crate::engine_server::mappings::test_utils; proptest! { #[test] fn round_trip(account in gens::account_arb()) { test_utils::protobuf_round_trip::<Account, state::Account>(account); } } }