-
Pascal Engélibert authoredPascal Engélibert authored
tests.rs 13.82 KiB
// Copyright 2021 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
use crate::mock::*;
use crate::{
Error, GenesisIdty, IdtyName, IdtyValue, NewOwnerKeyPayload, RevocationPayload,
NEW_OWNER_KEY_PAYLOAD_PREFIX, REVOCATION_PAYLOAD_PREFIX,
};
use codec::Encode;
use frame_support::{assert_noop, assert_ok};
use sp_runtime::testing::TestSignature;
type IdtyVal = IdtyValue<u64, u64, ()>;
fn alice() -> GenesisIdty<Test> {
GenesisIdty {
index: 1,
name: IdtyName::from("Alice"),
value: IdtyVal {
data: (),
next_creatable_identity_on: 0,
old_owner_key: None,
owner_key: 1,
removable_on: 0,
status: crate::IdtyStatus::Validated,
},
}
}
fn bob() -> GenesisIdty<Test> {
GenesisIdty {
index: 2,
name: IdtyName::from("Bob"),
value: IdtyVal {
data: (),
next_creatable_identity_on: 0,
old_owner_key: None,
owner_key: 2,
removable_on: 0,
status: crate::IdtyStatus::Validated,
},
}
}
#[test]
fn test_no_identity() {
new_test_ext(IdentityConfig {
identities: Vec::new(),
})
.execute_with(|| {
assert_eq!(Identity::identities_count(), 0);
});
}
#[test]
fn test_create_identity_ok() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
// We need to initialize at least one block before any call
run_to_block(1);
// Alice should be able to create an identity
assert_ok!(Identity::create_identity(RuntimeOrigin::signed(1), 2));
System::assert_has_event(RuntimeEvent::Identity(crate::Event::IdtyCreated {
idty_index: 2,
owner_key: 2,
}));
});
}
#[test]
fn test_create_identity_but_not_confirm_it() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
// We need to initialize at least one block before any call
run_to_block(1);
// Alice should be able to create an identity
assert_ok!(Identity::create_identity(RuntimeOrigin::signed(1), 2));
// The identity shoud expire in blocs #3
run_to_block(3);
System::assert_has_event(RuntimeEvent::Identity(crate::Event::IdtyRemoved {
idty_index: 2,
}));
// We shoud be able to recreate the identity
run_to_block(4);
assert_ok!(Identity::create_identity(RuntimeOrigin::signed(1), 2));
System::assert_has_event(RuntimeEvent::Identity(crate::Event::IdtyCreated {
idty_index: 3,
owner_key: 2,
}));
});
}
#[test]
fn test_idty_creation_period() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
// We need to initialize at least one block before any call
run_to_block(1);
// Alice should be able to create an identity
assert_ok!(Identity::create_identity(RuntimeOrigin::signed(1), 2));
System::assert_has_event(RuntimeEvent::Identity(crate::Event::IdtyCreated {
idty_index: 2,
owner_key: 2,
}));
assert_eq!(Identity::identity(1).unwrap().next_creatable_identity_on, 4);
// Alice cannot create a new identity before block #4
run_to_block(2);
assert_eq!(
Identity::create_identity(RuntimeOrigin::signed(1), 3),
Err(Error::<Test>::NotRespectIdtyCreationPeriod.into())
);
// Alice should be able to create a second identity after block #4
run_to_block(4);
assert_ok!(Identity::create_identity(RuntimeOrigin::signed(1), 3));
System::assert_has_event(RuntimeEvent::Identity(crate::Event::IdtyCreated {
idty_index: 3,
owner_key: 3,
}));
});
}
#[test]
fn test_change_owner_key() {
new_test_ext(IdentityConfig {
identities: vec![alice(), bob()],
})
.execute_with(|| {
let genesis_hash = System::block_hash(0);
let old_owner_key = 1u64;
let mut new_key_payload = NewOwnerKeyPayload {
genesis_hash: &genesis_hash,
idty_index: 1u64,
old_owner_key: &old_owner_key,
};
// We need to initialize at least one block before any call
run_to_block(1);
// Verify genesis data
assert_eq!(System::sufficients(&1), 1);
assert_eq!(System::sufficients(&10), 0);
// Caller should have an associated identity
assert_noop!(
Identity::change_owner_key(
RuntimeOrigin::signed(42),
10,
TestSignature(10, (NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode())
),
Error::<Test>::IdtyIndexNotFound
);
// Payload must be signed by the new key
assert_noop!(
Identity::change_owner_key(
RuntimeOrigin::signed(1),
10,
TestSignature(42, (NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode())
),
Error::<Test>::InvalidNewOwnerKeySig
);
// Payload must be prefixed
assert_noop!(
Identity::change_owner_key(
RuntimeOrigin::signed(1),
10,
TestSignature(10, new_key_payload.encode())
),
Error::<Test>::InvalidNewOwnerKeySig
);
// New owner key should not be used by another identity
assert_noop!(
Identity::change_owner_key(
RuntimeOrigin::signed(1),
2,
TestSignature(2, (NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode())
),
Error::<Test>::OwnerKeyAlreadyUsed
);
// Alice can change her owner key
assert_ok!(Identity::change_owner_key(
RuntimeOrigin::signed(1),
10,
TestSignature(10, (NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode())
));
assert_eq!(
Identity::identity(1),
Some(IdtyVal {
data: (),
next_creatable_identity_on: 0,
old_owner_key: Some((1, 1)),
owner_key: 10,
removable_on: 0,
status: crate::IdtyStatus::Validated,
})
);
// Alice still sufficient
assert_eq!(System::sufficients(&1), 1);
// New owner key should become a sufficient account
assert_eq!(System::sufficients(&10), 1);
run_to_block(2);
// Alice can't re-change her owner key too early
new_key_payload.old_owner_key = &10;
assert_noop!(
Identity::change_owner_key(
RuntimeOrigin::signed(10),
100,
TestSignature(
100,
(NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode()
)
),
Error::<Test>::OwnerKeyAlreadyRecentlyChanged
);
// Alice can re-change her owner key after ChangeOwnerKeyPeriod blocs
run_to_block(2 + <Test as crate::Config>::ChangeOwnerKeyPeriod::get());
assert_ok!(Identity::change_owner_key(
RuntimeOrigin::signed(10),
100,
TestSignature(
100,
(NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode()
)
));
// Old old owner key should not be sufficient anymore
assert_eq!(System::sufficients(&1), 0);
// Old owner key should still sufficient
assert_eq!(System::sufficients(&10), 1);
// New owner key should become a sufficient account
assert_eq!(System::sufficients(&100), 1);
// Revoke identity 1
assert_ok!(Identity::revoke_identity(
RuntimeOrigin::signed(42),
1,
100,
TestSignature(
100,
(
REVOCATION_PAYLOAD_PREFIX,
RevocationPayload {
idty_index: 1u64,
genesis_hash: System::block_hash(0),
}
)
.encode()
)
));
// Old owner key should not be sufficient anymore
assert_eq!(System::sufficients(&10), 0);
// Last owner key should not be sufficient anymore
assert_eq!(System::sufficients(&100), 0);
});
}
#[test]
fn test_idty_revocation_with_old_key() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
let genesis_hash = System::block_hash(0);
let new_key_payload = NewOwnerKeyPayload {
genesis_hash: &genesis_hash,
idty_index: 1u64,
old_owner_key: &1u64,
};
let revocation_payload = RevocationPayload {
idty_index: 1u64,
genesis_hash,
};
// We need to initialize at least one block before any call
run_to_block(1);
// Change alice owner key
assert_ok!(Identity::change_owner_key(
RuntimeOrigin::signed(1),
10,
TestSignature(10, (NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode())
));
assert!(Identity::identity(&1).is_some());
let idty_val = Identity::identity(&1).unwrap();
assert_eq!(idty_val.owner_key, 10);
assert_eq!(idty_val.old_owner_key, Some((1, 1)));
// We should be able to revoke Alice identity with old key
run_to_block(2);
assert_ok!(Identity::revoke_identity(
RuntimeOrigin::signed(42),
1,
1,
TestSignature(1, (REVOCATION_PAYLOAD_PREFIX, revocation_payload).encode())
));
//run_to_block(2 + <Test as crate::Config>::ChangeOwnerKeyPeriod::get());
});
}
#[test]
fn test_idty_revocation_with_old_key_after_old_key_expiration() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
let genesis_hash = System::block_hash(0);
let new_key_payload = NewOwnerKeyPayload {
genesis_hash: &genesis_hash,
idty_index: 1u64,
old_owner_key: &1u64,
};
let revocation_payload = RevocationPayload {
idty_index: 1u64,
genesis_hash,
};
// We need to initialize at least one block before any call
run_to_block(1);
// Change alice owner key
assert_ok!(Identity::change_owner_key(
RuntimeOrigin::signed(1),
10,
TestSignature(10, (NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode())
));
assert!(Identity::identity(&1).is_some());
let idty_val = Identity::identity(&1).unwrap();
assert_eq!(idty_val.owner_key, 10);
assert_eq!(idty_val.old_owner_key, Some((1, 1)));
// We should not be able to revoke Alice identity with old key after ChangeOwnerKeyPeriod
run_to_block(2 + <Test as crate::Config>::ChangeOwnerKeyPeriod::get());
assert_noop!(
Identity::revoke_identity(
RuntimeOrigin::signed(42),
1,
1,
TestSignature(1, (REVOCATION_PAYLOAD_PREFIX, revocation_payload).encode())
),
Error::<Test>::InvalidRevocationKey
);
});
}
#[test]
fn test_idty_revocation() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
let revocation_payload = RevocationPayload {
idty_index: 1u64,
genesis_hash: System::block_hash(0),
};
// We need to initialize at least one block before any call
run_to_block(1);
// Payload must be signed by the right identity
assert_eq!(
Identity::revoke_identity(
RuntimeOrigin::signed(1),
1,
42,
TestSignature(42, (REVOCATION_PAYLOAD_PREFIX, revocation_payload).encode())
),
Err(Error::<Test>::InvalidRevocationKey.into())
);
// Payload must be prefixed
assert_eq!(
Identity::revoke_identity(
RuntimeOrigin::signed(1),
1,
1,
TestSignature(1, revocation_payload.encode())
),
Err(Error::<Test>::InvalidRevocationSig.into())
);
// Anyone can submit a revocation payload
assert_ok!(Identity::revoke_identity(
RuntimeOrigin::signed(42),
1,
1,
TestSignature(1, (REVOCATION_PAYLOAD_PREFIX, revocation_payload).encode())
));
System::assert_has_event(RuntimeEvent::System(frame_system::Event::KilledAccount {
account: 1,
}));
System::assert_has_event(RuntimeEvent::Identity(crate::Event::IdtyRemoved {
idty_index: 1,
}));
run_to_block(2);
// The identity no longer exists
assert_eq!(
Identity::revoke_identity(
RuntimeOrigin::signed(1),
1,
1,
TestSignature(1, (REVOCATION_PAYLOAD_PREFIX, revocation_payload).encode())
),
Err(Error::<Test>::IdtyNotFound.into())
);
});
}