Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion concordium-base
Submodule concordium-base updated 43 files
+1 −1 concordium-grpc-api
+61 −21 haskell-src/Concordium/GRPC2.hs
+1 −1 haskell-src/Concordium/Types/DummyData.hs
+39 −15 haskell-src/Concordium/Types/Execution.hs
+46 −1 haskell-src/Concordium/Types/ProtocolVersion.hs
+35 −27 haskell-src/Concordium/Types/Queries.hs
+390 −67 haskell-src/Concordium/Types/Transactions.hs
+47 −17 haskell-tests/Generators.hs
+90 −6 haskell-tests/Types/TransactionSerializationSpec.hs
+2 −1 identity-provider-service/Cargo.lock
+2 −1 idiss/Cargo.lock
+2 −1 mobile_wallet/Cargo.lock
+4 −4 mobile_wallet/src/lib.rs
+2 −1 rust-bins/Cargo.lock
+8 −8 rust-bins/src/bin/client.rs
+2 −2 rust-bins/src/bin/generate_testdata.rs
+8 −2 rust-bins/src/bin/identity_provider_cli.rs
+6 −6 rust-bins/src/bin/user_cli.rs
+2 −1 rust-src/Cargo.lock
+23 −0 rust-src/concordium_base/CHANGELOG.md
+5 −1 rust-src/concordium_base/Cargo.toml
+1 −1 rust-src/concordium_base/benches/compute_message.rs
+10 −4 rust-src/concordium_base/benches/verify_cdi.rs
+19 −61 rust-src/concordium_base/src/base.rs
+4 −0 rust-src/concordium_base/src/common/serialize.rs
+91 −21 rust-src/concordium_base/src/common/types.rs
+7 −3 rust-src/concordium_base/src/id/account_holder.rs
+139 −13 rust-src/concordium_base/src/id/constants.rs
+1 −1 rust-src/concordium_base/src/id/ffi.rs
+12 −7 rust-src/concordium_base/src/id/id_proof_types.rs
+26 −21 rust-src/concordium_base/src/id/id_verifier.rs
+114 −12 rust-src/concordium_base/src/id/secret_sharing.rs
+4 −2 rust-src/concordium_base/src/id/test.rs
+456 −6 rust-src/concordium_base/src/transactions.rs
+39 −36 rust-src/concordium_base/src/updates.rs
+46 −18 rust-src/concordium_base/src/web3id/mod.rs
+1 −1 rust-src/wallet_library/src/credential.rs
+3 −3 rust-src/wallet_library/src/default_wallet_config.rs
+2 −2 rust-src/wallet_library/src/identity.rs
+4 −4 rust-src/wallet_library/src/statement.rs
+2 −0 smart-contracts/contracts-common/concordium-contracts-common-derive/CHANGELOG.md
+5 −15 smart-contracts/contracts-common/concordium-contracts-common-derive/src/lib.rs
+4 −4 smart-contracts/contracts-common/concordium-contracts-common/src/types.rs
3 changes: 2 additions & 1 deletion plt/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 106 additions & 27 deletions plt/plt-token-module/src/token_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@
//!

use crate::token_kernel_interface::*;
use concordium_base::base::AccountIndex;
use concordium_base::common;
use concordium_base::common::cbor;
use concordium_base::common::cbor::{SerializationOptions, UnknownMapKeys, cbor_encode};
use concordium_base::common::cbor::{
CborDeserialize, CborSerializationError, CborSerializationResult, SerializationOptions,
UnknownMapKeys,
};
use concordium_base::contracts_common::AccountAddress;
use concordium_base::protocol_level_tokens::{
RawCbor, TokenAmount, TokenModuleInitializationParameters,
CborHolderAccount, MetadataUrl, RawCbor, TokenAmount, TokenModuleInitializationParameters,
TokenModuleState,
};

/// Extension trait for `TokenKernelOperations` to provide convenience wrappers for
/// module state access and updating.
/// module state updates.
trait KernelOperationsExt: TokenKernelOperations {
/// Set or clear a value in the token module state at the corresponding key.
fn set_module_state<'a>(
Expand All @@ -25,6 +31,17 @@ trait KernelOperationsExt: TokenKernelOperations {

impl<T: TokenKernelOperations> KernelOperationsExt for T {}

/// Extension trait for `TokenQueryOperations` to provide convenience wrappers for
/// module state access.
trait KernelQueriesExt: TokenKernelQueries {
/// Get value from the token module state at the given key.
fn get_module_state<'a>(&self, key: impl IntoIterator<Item = &'a u8>) -> Option<StateValue> {
self.get_token_state(module_state_key(key))
}
}

impl<T: TokenKernelQueries> KernelQueriesExt for T {}

/// Little-endian prefix used to distinguish module state keys.
const MODULE_STATE_PREFIX: [u8; 2] = 0u16.to_le_bytes();

Expand All @@ -43,6 +60,8 @@ fn module_state_key<'a>(key: impl IntoIterator<Item = &'a u8>) -> StateKey {
pub enum TokenInitializationError {
#[error("Invalid token initialization parameters: {0}")]
InvalidInitializationParameters(String),
#[error("CBOR serialization error during token initialization: {0}")]
CborSerialization(#[from] CborSerializationError),
#[error("{0}")]
LockedStateKey(#[from] LockedStateKeyError),
#[error("The given governance account does not exist: {0}")]
Expand All @@ -55,11 +74,19 @@ pub enum TokenInitializationError {

/// Represents the reasons why [`execute_token_update_transaction`] can fail.
#[derive(Debug, thiserror::Error)]
pub enum TokenUpdateError {}
pub enum TokenUpdateError {
#[error("CBOR serialization error during token update: {0}")]
CborSerialization(#[from] CborSerializationError),
}

/// Represents the reasons why a query to the token module can fail.
#[derive(Debug)]
pub enum TokenQueryError {}
#[derive(Debug, thiserror::Error)]
pub enum TokenQueryError {
#[error("CBOR serialization error during token query: {0}")]
CborSerialization(#[from] CborSerializationError),
#[error("Token module state invariant broken: {0}")]
StateInvariantViolation(String),
}

/// The context for a token-holder or token-governance transaction.
#[derive(Debug)]
Expand Down Expand Up @@ -99,26 +126,24 @@ const STATE_KEY_ALLOW_LIST: &[u8] = b"allowList";
const STATE_KEY_DENY_LIST: &[u8] = b"denyList";
const STATE_KEY_MINTABLE: &[u8] = b"mintable";
const STATE_KEY_BURNABLE: &[u8] = b"burnable";
const STATE_KEY_PAUSED: &[u8] = b"paused";
const STATE_KEY_GOVERNANCE_ACCOUNT: &[u8] = b"governanceAccount";

fn cbor_decode<T: CborDeserialize>(cbor: impl AsRef<[u8]>) -> CborSerializationResult<T> {
let decode_options = SerializationOptions {
unknown_map_keys: UnknownMapKeys::Fail,
};
cbor::cbor_decode_with_options(cbor, decode_options)
}

/// Initialize a PLT by recording the relevant configuration parameters in the state and
/// (if necessary) minting the initial supply to the token governance account.
pub fn initialize_token(
host: &mut impl TokenKernelOperations,
initialization_parameters_cbor: RawCbor,
) -> Result<(), TokenInitializationError> {
let decode_options = SerializationOptions {
unknown_map_keys: UnknownMapKeys::Fail,
};
let init_params: TokenModuleInitializationParameters =
cbor::cbor_decode_with_options(initialization_parameters_cbor, decode_options).map_err(
|err| {
TokenInitializationError::InvalidInitializationParameters(format!(
"Error decoding token initialization parameters: {}",
err
))
},
)?;
cbor_decode(initialization_parameters_cbor)?;
if !init_params.additional.is_empty() {
return Err(TokenInitializationError::InvalidInitializationParameters(
format!(
Expand Down Expand Up @@ -148,12 +173,7 @@ pub fn initialize_token(
)
})?;
host.set_module_state(STATE_KEY_NAME, Some(name.into()))?;
let encoded_metadata = cbor_encode(&metadata).map_err(|err| {
TokenInitializationError::InvalidInitializationParameters(format!(
"Error encoding token metadata: {}",
err
))
})?;
let encoded_metadata = cbor::cbor_encode(&metadata)?;
host.set_module_state(STATE_KEY_METADATA, Some(encoded_metadata))?;
if init_params.allow_list == Some(true) {
host.set_module_state(STATE_KEY_ALLOW_LIST, Some(vec![]))?;
Expand All @@ -174,7 +194,7 @@ pub fn initialize_token(
let governance_account_index = host.account_index(&governance_account);
host.set_module_state(
STATE_KEY_GOVERNANCE_ACCOUNT,
Some(governance_account_index.index.to_be_bytes().to_vec()),
Some(common::to_bytes(&governance_account_index.index)),
)?;
if let Some(initial_supply) = init_params.initial_supply {
let mint_amount = to_token_raw_amount(initial_supply, host.decimals())?;
Expand Down Expand Up @@ -239,14 +259,73 @@ pub fn execute_token_update_transaction<Kernel: TokenKernelOperations>(

/// Get the CBOR-encoded representation of the token module state.
pub fn query_token_module_state<Kernel: TokenKernelQueries>(
_kernel: &impl TokenKernelQueries,
kernel: &Kernel,
) -> Result<RawCbor, TokenQueryError> {
todo!()
let name = kernel
.get_module_state(STATE_KEY_NAME)
.ok_or_else(|| TokenQueryError::StateInvariantViolation("Name not present".to_string()))
.and_then(|value| {
String::from_utf8(value).map_err(|err| {
TokenQueryError::StateInvariantViolation(format!("Name invalid UTF8: {}", err))
})
})?;

let metadata_cbor = kernel.get_module_state(STATE_KEY_METADATA).ok_or_else(|| {
TokenQueryError::StateInvariantViolation("Metadata not present".to_string())
})?;
let metadata: MetadataUrl = cbor_decode(metadata_cbor)?;

let allow_list = kernel.get_module_state(STATE_KEY_ALLOW_LIST).is_some();
let deny_list = kernel.get_module_state(STATE_KEY_DENY_LIST).is_some();
let mintable = kernel.get_module_state(STATE_KEY_MINTABLE).is_some();
let burnable = kernel.get_module_state(STATE_KEY_BURNABLE).is_some();
let paused = kernel.get_module_state(STATE_KEY_PAUSED).is_some();

let governance_account_index = AccountIndex::from(
kernel
.get_module_state(STATE_KEY_GOVERNANCE_ACCOUNT)
.ok_or_else(|| {
TokenQueryError::StateInvariantViolation(
"Governance account not present".to_string(),
)
})
.and_then(|value| {
common::from_bytes::<u64, _>(&mut value.as_slice()).map_err(|err| {
TokenQueryError::StateInvariantViolation(format!(
"Governance account index cannot be decoded: {}",
err
))
})
})?,
);
let governance_account = kernel
.account_by_index(governance_account_index)
.ok_or_else(|| {
TokenQueryError::StateInvariantViolation(format!(
"Governance account with index {} does not exist",
governance_account_index
))
})?;
let governance_account_address = kernel.account_canonical_address(&governance_account);

let state = TokenModuleState {
name: Some(name),
metadata: Some(metadata),
governance_account: Some(CborHolderAccount::from(governance_account_address)),
allow_list: Some(allow_list),
deny_list: Some(deny_list),
mintable: Some(mintable),
burnable: Some(burnable),
paused: Some(paused),
additional: Default::default(),
};

Ok(RawCbor::from(cbor::cbor_encode(&state)?))
}

/// Get the CBOR-encoded representation of the token module account state.
pub fn query_account_state<Kernel: TokenKernelQueries>(
_kernel: &impl TokenKernelQueries,
_kernel: &Kernel,
_account: Kernel::Account,
) -> Result<Option<RawCbor>, TokenQueryError> {
todo!()
Expand Down
9 changes: 5 additions & 4 deletions plt/plt-token-module/tests/kernel_stub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use concordium_base::contracts_common::AccountAddress;
use concordium_base::protocol_level_tokens::TokenModuleEventType;
use concordium_base::transactions::Memo;
use plt_token_module::token_kernel_interface::{
AmountNotRepresentableError, InsufficientBalanceError, LockedStateKeyError, RawTokenAmount,
StateKey, StateValue, TokenKernelOperations, TokenKernelQueries,
AmountNotRepresentableError, InsufficientBalanceError, LockedStateKeyError, OutOfEnergyError,
RawTokenAmount, StateKey, StateValue, TokenKernelOperations, TokenKernelQueries,
};

/// Token kernel stub providing an implementation of [`TokenKernelOperations`] and methods for
Expand All @@ -16,9 +16,10 @@ pub struct KernelStub {
/// List of accounts existing.
accounts: Vec<Account>,
/// Token managed state.
pub state: HashMap<StateKey, StateValue>,
state: HashMap<StateKey, StateValue>,
/// Decimal places in token representation.
decimals: u8,
/// Counter for creating accounts in the stub
next_account_index: AccountIndex,
}

Expand Down Expand Up @@ -193,7 +194,7 @@ impl TokenKernelOperations for KernelStub {
Ok(res)
}

fn tick_energy(&mut self, _energy: Energy) {
fn tick_energy(&mut self, _energy: Energy) -> Result<(), OutOfEnergyError> {
todo!()
}

Expand Down
Loading
Loading