-
Notifications
You must be signed in to change notification settings - Fork 276
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat!: recognize and activate accounts
BREAKING_CHANGE: - `Account` contains `is_active` field - `AccountEvent::Created` divides into `Recognized` and `Activated` - `ValidationFail` contains `UnrecognizedAuthority` and `InactiveAuthority` variants Signed-off-by: Shunkichi Sato <[email protected]>
- Loading branch information
Showing
26 changed files
with
495 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
mod private; | ||
mod public; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
//! In private use cases, a new account should be: | ||
//! - recognized when targeted as (a part of) a destination (or an object) of a creative instruction | ||
//! - becomes able to hold assets, permissions, roles, and metadata | ||
//! - cannot yet execute any queries or transactions | ||
//! - activated when manually registered by an administrative account | ||
//! - becomes able to execute queries and transactions | ||
use iroha::data_model::prelude::*; | ||
use test_network::*; | ||
use test_samples::{gen_account_in, ALICE_ID}; | ||
|
||
/// A new account e.g. "carol" should be: | ||
/// - recognized when targeted as a destination of a transfer of numeric asset e.g. "rose" | ||
/// - activated when manually registered by an administrative account e.g. "alice" | ||
/// | ||
/// # Scenario | ||
/// | ||
/// 0. new carol targeted ... carol recognized | ||
/// 0. carol tries query ... err | ||
/// 0. carol tries transaction ... err | ||
/// 0. register carol ... carol activated | ||
/// 0. carol tries query ... ok | ||
/// 0. carol tries transaction ... ok | ||
#[test] | ||
fn on_transfer_asset_numeric() { | ||
let (_rt, _peer, client_alice) = <PeerBuilder>::new().with_port(10_820).start_with_runtime(); | ||
wait_for_genesis_committed(&[client_alice.clone()], 0); | ||
let observer = client_alice.clone(); | ||
|
||
// new carol targeted ... carol recognized | ||
let (carol_id, carol_keypair) = gen_account_in("wonderland"); | ||
let _ = observer | ||
.request(FindAccountById::new(carol_id.clone())) | ||
.expect_err("carol should not be recognized at this point"); | ||
let rose: AssetDefinitionId = "rose#wonderland".parse().unwrap(); | ||
let rose_alice = AssetId::new(rose.clone(), ALICE_ID.clone()); | ||
let n_roses_alice = observer | ||
.request(FindAssetQuantityById::new(rose_alice.clone())) | ||
.expect("alice should have roses"); | ||
assert!(numeric!(3) < n_roses_alice); | ||
let transfer = Transfer::asset_numeric(rose_alice, 3_u32, carol_id.clone()); | ||
client_alice | ||
.submit_blocking(transfer) | ||
.expect("alice should succeed to transfer"); | ||
let _ = observer | ||
.request(FindAccountById::new(carol_id.clone())) | ||
.expect("carol should be recognized now"); | ||
let rose_carol = AssetId::new(rose.clone(), carol_id.clone()); | ||
let n_roses_carol = observer | ||
.request(FindAssetQuantityById::new(rose_carol.clone())) | ||
.expect("carol should have roses"); | ||
assert_eq!(n_roses_carol, numeric!(3)); | ||
|
||
// carol tries query ... err | ||
let client_carol = { | ||
let mut client = client_alice.clone(); | ||
client.key_pair = carol_keypair; | ||
client.account_id = carol_id.clone(); | ||
client | ||
}; | ||
let query = FindAssetQuantityById::new(rose_carol.clone()); | ||
let _ = client_carol | ||
.request(query.clone()) | ||
.expect_err("queries from inactive carol should be rejected"); | ||
|
||
// carol tries transaction ... err | ||
let instruction = Log::new( | ||
iroha_data_model::Level::DEBUG, | ||
"the one least likely to be rejected".to_string(), | ||
); | ||
let _ = client_carol | ||
.submit_blocking(instruction.clone()) | ||
.expect_err("transactions from inactive carol should be rejected"); | ||
|
||
// register carol ... carol activated | ||
let register = Register::account(Account::new(carol_id.clone())); | ||
client_alice | ||
.submit_blocking(register) | ||
.expect("alice should succeed to register"); | ||
|
||
// carol tries query ... ok | ||
let _ = client_carol | ||
.request(query) | ||
.expect("queries from active carol should be accepted"); | ||
|
||
// carol tries transaction ... ok | ||
client_carol | ||
.submit_blocking(instruction) | ||
.expect("transactions from active carol should be accepted"); | ||
} |
102 changes: 102 additions & 0 deletions
102
client/tests/integration/account_registration/public.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
//! In public use cases, a new account should be: | ||
//! - recognized when targeted as (a part of) a destination (or an object) of a creative instruction | ||
//! - becomes able to hold assets, permissions, roles, and metadata | ||
//! - cannot yet execute any queries or transactions | ||
//! - automatically activated by an administrative trigger | ||
//! - becomes able to execute queries and transactions | ||
use eyre::Result; | ||
use iroha::data_model::prelude::*; | ||
use test_network::*; | ||
use test_samples::{gen_account_in, ALICE_ID}; | ||
|
||
/// A new account e.g. "carol" should be: | ||
/// - recognized when targeted as a destination of a transfer of numeric asset e.g. "rose" | ||
/// - automatically activated by an administrative trigger | ||
/// | ||
/// # Scenario | ||
/// | ||
/// 0. ... administrative trigger registered | ||
/// 0. new carol targeted ... carol recognized | ||
/// 0. clock forward by one block ... carol activated | ||
/// 0. carol tries query ... ok | ||
/// 0. carol tries transaction ... ok | ||
#[test] | ||
fn on_transfer_asset_numeric() -> Result<()> { | ||
let (_rt, _peer, client_alice) = <PeerBuilder>::new().with_port(10_810).start_with_runtime(); | ||
wait_for_genesis_committed(&[client_alice.clone()], 0); | ||
let observer = client_alice.clone(); | ||
|
||
// ... administrative trigger registered | ||
let wasm = iroha_wasm_builder::Builder::new( | ||
"tests/integration/smartcontracts/trigger_activate_account", | ||
) | ||
.show_output() | ||
.build()? | ||
.optimize()? | ||
.into_bytes()?; | ||
let register_activator = Register::trigger(Trigger::new( | ||
"activator$wonderland".parse().unwrap(), | ||
Action::new( | ||
WasmSmartContract::from_compiled(wasm), | ||
Repeats::Indefinitely, | ||
ALICE_ID.clone(), | ||
AccountEventFilter::new().for_events(AccountEventSet::Recognized), | ||
), | ||
)); | ||
client_alice | ||
.submit_blocking(register_activator) | ||
.expect("alice should succeed to register activator"); | ||
|
||
// new carol targeted ... carol recognized | ||
let (carol_id, carol_keypair) = gen_account_in("wonderland"); | ||
let _ = observer | ||
.request(FindAccountById::new(carol_id.clone())) | ||
.expect_err("carol should not be recognized at this point"); | ||
let rose: AssetDefinitionId = "rose#wonderland".parse().unwrap(); | ||
let rose_alice = AssetId::new(rose.clone(), ALICE_ID.clone()); | ||
let n_roses_alice = observer | ||
.request(FindAssetQuantityById::new(rose_alice.clone())) | ||
.expect("alice should have roses"); | ||
assert!(numeric!(3) < n_roses_alice); | ||
let transfer = Transfer::asset_numeric(rose_alice, 3_u32, carol_id.clone()); | ||
client_alice | ||
.submit_blocking(transfer) | ||
.expect("alice should succeed to transfer"); | ||
let _ = observer | ||
.request(FindAccountById::new(carol_id.clone())) | ||
.expect("carol should be recognized now"); | ||
let rose_carol = AssetId::new(rose.clone(), carol_id.clone()); | ||
let n_roses_carol = observer | ||
.request(FindAssetQuantityById::new(rose_carol.clone())) | ||
.expect("carol should have roses"); | ||
assert_eq!(n_roses_carol, numeric!(3)); | ||
|
||
// clock forward by one block ... carol activated | ||
let instruction = Log::new( | ||
iroha_data_model::Level::DEBUG, | ||
"the one least likely to be rejected".to_string(), | ||
); | ||
client_alice | ||
.submit_blocking(instruction.clone()) | ||
.expect("instruction should succeed"); | ||
|
||
// carol tries query ... ok | ||
let client_carol = { | ||
let mut client = client_alice.clone(); | ||
client.key_pair = carol_keypair; | ||
client.account_id = carol_id.clone(); | ||
client | ||
}; | ||
let query = FindAssetQuantityById::new(rose_carol.clone()); | ||
let _ = client_carol | ||
.request(query) | ||
.expect("queries from active carol should be accepted"); | ||
|
||
// carol tries transaction ... ok | ||
client_carol | ||
.submit_blocking(instruction) | ||
.expect("transactions from active carol should be accepted"); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
mod account_registration; | ||
mod add_domain; | ||
mod asset; | ||
mod asset_propagation; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
client/tests/integration/smartcontracts/trigger_activate_account/Cargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[package] | ||
name = "trigger_activate_account" | ||
|
||
edition.workspace = true | ||
version.workspace = true | ||
authors.workspace = true | ||
|
||
license.workspace = true | ||
|
||
[lib] | ||
crate-type = ['cdylib'] | ||
|
||
[dependencies] | ||
iroha_trigger.workspace = true | ||
|
||
panic-halt.workspace = true | ||
lol_alloc.workspace = true | ||
getrandom.workspace = true |
30 changes: 30 additions & 0 deletions
30
client/tests/integration/smartcontracts/trigger_activate_account/src/lib.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
//! Trigger responsible for activating newly recognized accounts in "wonderland" | ||
#![no_std] | ||
|
||
#[cfg(not(test))] | ||
extern crate panic_halt; | ||
|
||
use iroha_trigger::prelude::*; | ||
use lol_alloc::{FreeListAllocator, LockedAllocator}; | ||
|
||
#[global_allocator] | ||
static ALLOC: LockedAllocator<FreeListAllocator> = LockedAllocator::new(FreeListAllocator::new()); | ||
|
||
getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); | ||
|
||
#[iroha_trigger::main] | ||
fn main(_id: TriggerId, _owner: AccountId, event: EventBox) { | ||
let EventBox::Data(DataEvent::Domain(DomainEvent::Account(AccountEvent::Recognized( | ||
account_id, | ||
)))) = event | ||
else { | ||
return; | ||
}; | ||
|
||
Register::account(Account::new(account_id)) | ||
.execute() | ||
.dbg_expect( | ||
"authority should be alice, and alice should succeed to register accounts in wonderland", | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.