feat(agent-identity): v0.0.26 — register_agent_did impl complete + mock runtime integration tests E2E (10 scenarios)
Phase 2.7 AGENT IDENTITY pallet REAL IMPL canonical. Full 8-step CHN-7 flow canonical register_agent_did dispatchable + storage assertions + Inmutable #41 Cross-Species Co-authorship enforcement compile-detect. Mock runtime + 10 integration tests E2E pattern v0.0.18 + v0.0.22 mirror. ## Real impl canonical 8-step CHN-7 1. ensure_signed(origin) 2. Idempotency check (!Identities::contains_key(&who)) 3. Derive DID canonical via derive_did(public_key) BLAKE3 (Inmutable #16) 4. DID collision check (!DidToAccount::contains_key(&did)) 5. Build AgentChain BoundedVec from co_authors_raw Vec<[u8;32]> (overflow → AgentChainOverflow) 6. Inmutable #41 enforce: Hybrid requires non-empty agent_chain 7. Storage insert: Identities + DidToAccount reverse lookup 8. Emit AgentRegistered + AgentBound (if cross-species) Pure helper Pallet::<T>::query_identity_of() para Runtime API v0.0.27. ## 10 integration tests E2E canonical - scenario_1: Human self-registration → ok + DID + empty chain - scenario_2: AGI self-registration → ok + Inmutable #41 sovereign - scenario_3: Hybrid + 2 co-authors → ok + AgentBound emitted - scenario_4: Hybrid + empty chain → Err::HybridRequiresAgentChain - scenario_5: duplicate account → Err::AlreadyRegistered - scenario_6: same pubkey diff account → Err::DidAlreadyTaken - scenario_7: 11 co-authors → Err::AgentChainOverflow (ConstU32<10>) - scenario_8: DID → Account reverse lookup canonical - scenario_9: Human + AGI both is_sovereign() (Inmutable #41 lobo blanco) - scenario_10: 8-step CHN-7 walkthrough explicit Pre/Post assertions ## Files - EDIT: crates/origin-chain-agent-identity/src/lib.rs (real impl 8-step + query_identity_of helper) - NEW: crates/origin-chain-agent-identity/src/mock.rs (80 LOC mock runtime) - NEW: crates/origin-chain-agent-identity/src/tests_integration.rs (310 LOC, 10 tests) - EDIT: CHANGELOG.md (v0.0.26 entry comprehensive) ## Verification - cargo test -p origin-chain-agent-identity — 16 tests verde canonical, 0 failures (10 integration + 4 standalone + 2 auto-generated) 🛠️ Phase 2.7 real impl canonical. Runtime API v0.0.27 next ship → Phase 2.7 COMPLETE. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
46a0188a1d
commit
2fefe4cf51
4 files changed
+533
-17
No files matched your search
@@ -102,9 +102,11 @@ sp_api::decl_runtime_apis! {
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use alloc::vec::Vec;
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
use origin_chain_types::{AgentIdentity, AgentKind, Did};
|
||||
use origin_chain_types::{AccountId, AgentChain, AgentIdentity, AgentKind, Did};
|
||||
use sp_runtime::traits::SaturatedConversion;
|
||||
|
||||
/// Pallet configuration trait canonical.
|
||||
///
|
||||
@@ -197,47 +199,119 @@ pub mod pallet {
|
||||
HybridRequiresAgentChain,
|
||||
}
|
||||
|
||||
/// Dispatchables canonical (scaffold v0.0.24 — real impl v0.0.26).
|
||||
/// Dispatchables canonical (real impl v0.0.26).
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// CHN-7 canonical: `register_agent_did` scaffold dispatchable.
|
||||
/// CHN-7 canonical: `register_agent_did` real dispatchable canonical.
|
||||
///
|
||||
/// **SCAFFOLD v0.0.24 canonical**: real impl deferred a v0.0.26. Current
|
||||
/// canonical solo validates basic state (origin signed + no duplicate)
|
||||
/// + emite placeholder event canonical.
|
||||
/// **Real impl v0.0.26**: Full 8-step canonical flow + storage assertions
|
||||
/// end-to-end + Inmutable #41 Cross-Species Co-authorship verification
|
||||
/// compile-detect.
|
||||
///
|
||||
/// Flow canonical 6-step per CHN-7 (v0.0.26 real):
|
||||
/// Flow canonical 8-step per CHN-7:
|
||||
/// 1. `ensure_signed(origin)` canonical
|
||||
/// 2. Validate `!Identities::contains_key(who)` (no duplicate)
|
||||
/// 2. Idempotency check: `!Identities::contains_key(&who)` (no duplicate)
|
||||
/// 3. Derive DID canonical via `derive_did(public_key)` BLAKE3
|
||||
/// 4. Validate `!DidToAccount::contains_key(did)` (no DID collision)
|
||||
/// 5. Validate Hybrid → agent_chain non-empty (Inmutable #41 verification)
|
||||
/// 6. Insert Identities + DidToAccount + emit AgentRegistered + AgentBound (if Hybrid)
|
||||
/// 4. DID collision check: `!DidToAccount::contains_key(&did)` (no collision)
|
||||
/// 5. Build `AgentChain` canonical `BoundedVec` (overflow → `AgentChainOverflow`)
|
||||
/// 6. Inmutable #41 enforce: Hybrid requires non-empty agent_chain
|
||||
/// 7. Insert storage canonical: `Identities` + `DidToAccount`
|
||||
/// 8. Emit `AgentRegistered` + `AgentBound` (if cross-species) canonical
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(Weight::from_parts(10_000, 0))]
|
||||
pub fn register_agent_did(
|
||||
origin: OriginFor<T>,
|
||||
_public_key: [u8; 32],
|
||||
public_key: [u8; 32],
|
||||
kind: AgentKind,
|
||||
co_authors_raw: Vec<[u8; 32]>,
|
||||
) -> DispatchResult {
|
||||
// Verify origin canonical signed.
|
||||
// Step 1: ensure origin signed canonical
|
||||
let who = ensure_signed(origin)?;
|
||||
|
||||
// SCAFFOLD v0.0.24: emit placeholder event canonical.
|
||||
// Real impl v0.0.26: derive_did + storage insert + cross-species validation.
|
||||
// Step 2: idempotency check canonical (no duplicate registration)
|
||||
ensure!(
|
||||
!Identities::<T>::contains_key(&who),
|
||||
Error::<T>::AlreadyRegistered
|
||||
);
|
||||
|
||||
// Step 3: derive DID canonical via BLAKE3 (Inmutable #16 byte-determinism)
|
||||
let did = crate::derive_did(&public_key);
|
||||
|
||||
// Step 4: DID collision check canonical
|
||||
ensure!(
|
||||
!DidToAccount::<T>::contains_key(did),
|
||||
Error::<T>::DidAlreadyTaken
|
||||
);
|
||||
|
||||
// Step 5: build AgentChain canonical BoundedVec<AccountId, ConstU32<10>>
|
||||
let mut agent_chain = AgentChain::default();
|
||||
for raw in co_authors_raw {
|
||||
agent_chain
|
||||
.try_push(AccountId::new(raw))
|
||||
.map_err(|_| Error::<T>::AgentChainOverflow)?;
|
||||
}
|
||||
|
||||
// Step 6: Inmutable #41 canonical enforce — Hybrid requires non-empty agent_chain
|
||||
if matches!(kind, AgentKind::Hybrid) && agent_chain.is_empty() {
|
||||
return Err(Error::<T>::HybridRequiresAgentChain.into());
|
||||
}
|
||||
|
||||
// Step 7: build AgentIdentity struct + insert storage canonical
|
||||
let has_cross_species = !agent_chain.is_empty();
|
||||
let co_author_count = agent_chain.len() as u32;
|
||||
let creator = AccountId::new(public_key);
|
||||
let block_number: u64 = <frame_system::Pallet<T>>::block_number()
|
||||
.saturated_into::<u64>();
|
||||
|
||||
let identity = AgentIdentity {
|
||||
did,
|
||||
kind,
|
||||
creator,
|
||||
registered_at_block: block_number,
|
||||
provenance_proof: None,
|
||||
agent_chain,
|
||||
};
|
||||
|
||||
Identities::<T>::insert(&who, identity);
|
||||
DidToAccount::<T>::insert(did, &who);
|
||||
|
||||
// Step 8: emit events canonical
|
||||
Self::deposit_event(Event::AgentRegistered {
|
||||
account: who,
|
||||
did: origin_chain_types::AssetHash::new([0u8; 32]), // placeholder until v0.0.26
|
||||
account: who.clone(),
|
||||
did,
|
||||
kind,
|
||||
});
|
||||
|
||||
if has_cross_species {
|
||||
Self::deposit_event(Event::AgentBound {
|
||||
account: who,
|
||||
co_author_count,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Pure helper canonical para Runtime API v0.0.27 consumer.
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Query identity canonical sin storage mutation (read-only canonical).
|
||||
pub fn query_identity_of(account: &T::AccountId) -> Option<AgentIdentity> {
|
||||
Identities::<T>::get(account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
// v0.0.26 — Mock runtime canonical + integration tests E2E CHN-7 flow.
|
||||
// Pattern v0.0.18 (Provenance) + v0.0.22 (Fees) mirror.
|
||||
#[cfg(test)]
|
||||
pub mod mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests_integration;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in new issue
Block a user