Ana içeriğe geç

CType 🎯

CTYPE, yani Claim Type, KILT protokolü için özel bir terimdir. Aslında, bu oldukça basit bir konsept: CTYPE bir claim ya da Türkçe'de iddianın veri modelidir. 📊

🌟 CTYPE'a Bakış 🌟
  • KILT, işletmeler ve tüketiciler için öz-yönetimli, doğrulanabilir kimlik bilgileri ve DID'ler sağlar. 🛡️ Ama hangi tür kimlik bilgilerinden bahsediyoruz? 🤔🔐

  • Kimlik bilgilerimizi nasıl saklayabiliriz? 🗂️ Doldurmamız gereken belirli bir form var mı? 📝 Tüm bu soruları yanıtlayacağız! 😎👍

  • Diyelim ki bazı verileri onaylatmak istiyorsunuz. 📋 Bu verilerin içinde adınız, konumunuz gibi daha küçük parçalar var. Peki, bu verileri bir onaylayıcıya nasıl sunacaksınız? 🤷‍♂️ Hangi şablonda? 📑

  • CTypes'ı tanıyalım! 🎉 CTypes, kimlik bilgilerinin şemalarıdır. 📋 İhtiyacınız olan "form oluşturma araçları" olarak hizmet edebilirler. 🛠️

  • CTypes, bir iddianın yapısını, veri modeli dahil, tanımlayan KILT'a özgü veri tipleridir. 📊✅ JSON Şeması'na dayanmaktadırlar, bu da JSON belgelerini açıklamak ve doğrulamak için kullanılan bir standarttır. 📜

  • Kendi CTypes'ınızı oluşturabilir 🛠️ ve bunları zincirde saklayabilir veya ihtiyacınızı karşılamak için zincirde zaten var olan CTypes'ı kullanabilirsiniz. 💡🔗

Attesterlar, bir attest yani onay işlemi yapmadan önce, hangi Ctype formatını destekleyeceklerini belirlemelidir. 🎯 Örneğin, sürücü kursları sadece ehliyetle alakalı onaylama yapabilirler, evin mesken alanı ile alakalı bir onaylama yapamazlar. 🚗🏠

🌠

CTYPE'lar standartlaşması hedeflenen öğelerdir. 🎯 Yeni bir Ctype oluşturmadan önce olanları kullanmak büyük ölçüde önerilir. 👍

Workshop'ta süreci öğrenmek için kendi CTYPE'ımızı yaratacağız! 🛠️🎉

📝

CType, bir credential'ın içerisinde gerekli tüm bilgilerin var olmasını teyit eder. 🛡️ Örneğin, bir ehliyette doğum tarihi, isim ve hangi tür aracın kullanılma izninin olduğu yer alır. 🚗📅 Bu bilgiler, ehliyetimizi kontrol eden polis memurunun bizi onaylaması için gerekli olan bilgilerdir. 🚓👮‍♂️

CType oluşturmak için zincir üzerinde bir full DID gereklidir. 🆔 Ayrıca, bu hesabın içerisinde PILT coinlerinin olduğundan emin olmalıyız, çünkü CType oluşturma işlemi bizden bir miktar ödeme alacak. 💰

Örnek bir CTYPE'a bakalım

Hadi kafamızda tam oturması için örnek bir CType incelelim, bu işlem için de yine ehliyeti örnek gösterebiliriz:

{
"$id": "kilt:ctype:0x4f1d68ac46daf4613181b33b16faaf10cf94879dc2246d7485dc2ccbb843641d",
"$schema": "ipfs://bafybeiah66wbkhqbqn7idkostj2iqyan2tstc4tpqt65udlhimd7hcxjyq/",
"additionalProperties": false,
"properties": {
"age": {
"type": "integer"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
}
},
"title": "Drivers License by did:kilt:4t9FPVbcN42UMxt3Z2Y4Wx38qPL8bLduAB11gLZSwn5hVEfH",
"type": "object"
}
ipucu

Yukarıdaki kod yapısını inceleyecek olursak ilk olarak bu yapının JSON formatına benzediğini görebiliriz ki bu durumda haklı oluruz. CType'lar temellerinde JavaScript Objeleri olarak tasarlanmıştır.

Satır satır bu niteliklere bakacak olursak:

AnahtarDeğer
$idBu CType'ın KILT kimliği. CType'ın dijital izi'ni temsil ettiği için en önemli özelliğidir.
$schemaBir CType'ın nasıl görünebileceğini tanımlayan meta-şemaya bir referans. İki versiyonu vardır.
titleCType'ın başlığı.
propertiesBu CType'a uygun bir iddianın sahip olabileceği özellikler.
typeTüm CType'lar için type bir nesnedir.
additionalPropertiesVarsayılan olarak false olarak ayarlanmıştır. Bu, bir iddiada istenmeyen özelliklerin sınırlanmasını sağlar.

Ctypelar KILT Blokzinciri üzerinde depolanmaktadır.

Gerçek hayatta CType'ları var olan bir depodan veya zincirden çekmemiz gerekmektedir.

Bu workshop içerisinde Attester bireyimiz kendi bir CType oluşturup test zincirine yükleyecektir.

CType Oluşturma

Ctype oluşturmak için alt kısımdaki gibi bir yapı oluşturabiliriz:

ctypeSchema
import * as Kilt from '@kiltprotocol/sdk-js'

// Return CType with the properties matching a given schema.
export function getCtypeSchema(): Kilt.ICType {
return Kilt.CType.fromProperties('Drivers License', {
name: {
type: 'string'
},
age: {
type: 'integer'
}
})
}

Bu kodun nasıl çalıştığına satır satır bakacak olursak:

  • İlk olarak KILT-SDK'yi kodumuzun içerisine eklemekle başlayabiliriz.
  • Sonrasında getCtypeSchema adın da bir fonksiyon tanımlanırız.
  • Son olarak gerekli bilgileri alarak CType.fromProperties fonksiyonu ile Ctype'a çevirmeye hazır hale getiririz.

CType'ı Elde Etme

Şimdi CTYPE'ların olup olmadığını kontrol ederek olmaması durumunda oluşturacak kodumuzu yazabiliriz.

Kütüphane Ekleme

generateCtype
import { config as envConfig } from 'dotenv'
import * as Kilt from '@kiltprotocol/sdk-js'
import { generateAccount } from './generateAccount'
import { generateKeypairs } from './generateKeypairs'
import { getCtypeSchema } from './ctypeSchema'

Bu kısımda eklediğimiz paketleri incelediğimizde daha önceden de eklediğimiz paketlerin yer aldığını görüntüleyebiliriz. Bu paketlerden daha önce kullanmadığımız getCtypeSchema gözümüze çarpabilir. Bu paket daha öncesinde yazdığımız ctypeSchema.ts dosyasından getCtypeSchema methoduna erişmektedir.

ensureStoredCtype Fonksiyonu

generateCtype
export async function ensureStoredCtype(
attesterAccount: Kilt.KiltKeyringPair,
attesterDid: Kilt.DidUri,
signCallback: Kilt.SignExtrinsicCallback
): Promise<Kilt.ICType> {
// ...
}

Tabii, ensureStoredCtype fonksiyonu üç parametre alıyor ve bir Promise döndürüyor. Fonksiyonun amacı, bir CType'ın (Claim Type) zaten KILT blockchain'de kayıtlı olup olmadığını kontrol etmek ve eğer değilse, onu oluşturmaktır. Bu parametrelere bakacak olursak:

  1. attesterAccount: Kilt.KiltKeyringPair: Bu, işlemleri imzalamak için kullanılacak olan KILT hesabının anahtar çiftini temsil eder.
  2. attesterDid: Kilt.DidUri: Bu, işlemleri yetkilendirmek için kullanılacak olan Decentralized Identifier (DID) URI'yi temsil eder.
  3. signCallback: Kilt.SignExtrinsicCallback: Bu, işlemi imzalamak için kullanılacak olan callback fonksiyonudur.
not

Promise<Kilt.ICType>: Fonksiyon, oluşturulan veya zaten var olan CType'ı döndüren bir Promise döndürür.

KILT API'sini Almak

generateCtype
const api = Kilt.ConfigService.get('api');

KILT API'sini alır, bu API üzerinden blockchain ile etkileşime geçilecektir.

CType Şemasını Almak

generateCtype
const ctype = getCtypeSchema();

Önceden tanımlanmış bir CType şemasını alır. Bu şemayı daha önce yazdığımız ctypeSchema.ts dosyasından elde etmektedir. Bu dosya içerisinden CType'ı alarak projemiz içerisine ekler.

CType'ın Olup Olmadığını Kontrol Etmek

generateCtype
try {
await Kilt.CType.verifyStored(ctype)
console.log('Ctype already stored. Skipping creation')
return ctype
} catch {
// ...
}

Oluşturacağımız CType'lar zincirde aynı şekilde var olabilir. Bu durumlarda yeniden bir CType'ı zincire eklemek bizlere gereksiz bir ücrete malolacaktır. Bu durumu önlemek için try yapısı içerisinde CType.verifyStored() methodu ile şemamızın var olup olmadığını kontrol edebiliriz. Eğer hali hazırda depolanmış ise bu durum kullanıcıya söylenir ve ctype'ı döndürerek devam eder.

Eğer Kayıtlı Değilse?

Ctype'ın kayıtlı olmaması durumunda catch yapısı çalışacaktır.

CType Oluşturmak ve Kaydetmek

Zincirde CType'ın bulunmadığına emin olduğumuzda zincire oluşturduğumuz CType'ı ekleyebiliriz.

generateCtype
console.log('Ctype not present. Creating it now...');
const encodedCtype = Kilt.CType.toChain(ctype);
const tx = api.tx.ctype.add(encodedCtype);

const extrinsic = await Kilt.Did.authorizeTx(
attesterDid,
tx,
signCallback,
attesterAccount.address
);
await Kilt.Blockchain.signAndSubmitTx(extrinsic, attesterAccount);
return ctype;

Üst Kısımda CType'ı oluşturup zincire eklememiz için gerekli kod ifade edilmiştir. Bu kodu sırasıyla inceleyecek olursak:

  • encodedCtype: Ctype'ı şema olarak oluşturduk ancak zincirin içerisine ekleyebileceğimiz şekilde şifrelememiz gerekmektedir. Bu işlemi CType.toChain() ile gerçekleştirebiliriz.
  • tx: CType'ı zincire eklememiz için bu CType'ın transferini gerçekleştirmemiz gerekmektedir. Bu transfer için de Ctype'ı tx.ctype.add fonksiyonu ile hazırlayabiliriz.
  • extrinsic: Zincire ekleyeceğimiz transferi uygun formata getirmek için kullanırız. Bu transfer sayesinde zincir ile etkileşime geçeceğimiz için attesterDid değerini kullanmamız gerekmektedir.
  • signAndSubmitTx: Son olarak işlemi zincire imzalayarak göndereririz.

Ana Kod Bloğu

Bu kısım yine diğer kodlarda olduğu gibi generateCtype.ts dosyası direkt olarak çağırılırsa nasıl çalışacağını ifade etmektedir.

generateCtype
if (require.main === module) {
;(async () => {
// ...
})()
}

Kodun direkt olarak çalıştırılıp çalıştırılmadığına bir if yapısı ile bakarız. Eğer direkt olarak çalıştırılıyorsa altında bulunan kodlar çalışır.

Çevre Değişkenleri ve Bağlantı

generateCtype
envConfig()
await Kilt.connect(process.env.WSS_ADDRESS as string)

Çevre değişkenleri yüklenir ve KILT blockchain'ine bağlanılır.

Hesap ve DID Oluşturma

generateCtype
const accountMnemonic = process.env.ATTESTER_ACCOUNT_MNEMONIC as string
const { account } = generateAccount(accountMnemonic)
const didMnemonic = process.env.ATTESTER_DID_MNEMONIC as string
const { authentication, assertionMethod } = generateKeypairs(didMnemonic)
const attesterDidUri = Kilt.Did.getFullDidUriFromKey(authentication)

Mnemonic kullanarak bir hesap ve DID (Decentralized Identifier) oluşturulur.

ensureStoredCtype Fonksiyonunun Çağrılması

generateCtype
await ensureStoredCtype(account, attesterDidUri, async ({ data }) => ({
signature: assertionMethod.sign(data),
keyType: assertionMethod.type
}))

ensureStoredCtype fonksiyonu çağrılır ve gerekli işlemler yapılır.

Genel Bir Bakış Yapalım

Hadi birlikte yazdığımız generateCtype.ts dosyasının nasıl çalıştığına tüm kodu bir arada görerek bakalım.

generateCtype
import { config as envConfig } from 'dotenv'

import * as Kilt from '@kiltprotocol/sdk-js'

import { generateAccount } from './generateAccount'
import { generateKeypairs } from './generateKeypairs'
import { getCtypeSchema } from './ctypeSchema'

export async function ensureStoredCtype(
attesterAccount: Kilt.KiltKeyringPair,
attesterDid: Kilt.DidUri,
signCallback: Kilt.SignExtrinsicCallback
): Promise<Kilt.ICType> {
const api = Kilt.ConfigService.get('api')

// Get the CTYPE and see if it's stored, if yes return it.
const ctype = getCtypeSchema()
try {
await Kilt.CType.verifyStored(ctype)
console.log('Ctype already stored. Skipping creation')
return ctype
} catch {
console.log('Ctype not present. Creating it now...')
// Authorize the tx.
const encodedCtype = Kilt.CType.toChain(ctype)
const tx = api.tx.ctype.add(encodedCtype)
const extrinsic = await Kilt.Did.authorizeTx(
attesterDid,
tx,
signCallback,
attesterAccount.address
)

// Write to chain then return the CType.
await Kilt.Blockchain.signAndSubmitTx(extrinsic, attesterAccount)

return ctype
}
}

// Don't execute if this is imported by another file.
if (require.main === module) {
;(async () => {
envConfig()

try {
await Kilt.connect(process.env.WSS_ADDRESS as string)

const accountMnemonic = process.env.ATTESTER_ACCOUNT_MNEMONIC as string
const { account } = generateAccount(accountMnemonic)

const didMnemonic = process.env.ATTESTER_DID_MNEMONIC as string
const { authentication, assertionMethod } = generateKeypairs(didMnemonic)
const attesterDidUri = Kilt.Did.getFullDidUriFromKey(authentication)

await ensureStoredCtype(account, attesterDidUri, async ({ data }) => ({
signature: assertionMethod.sign(data),
keyType: assertionMethod.type
}))
} catch (e) {
console.log('Error while checking on chain ctype')
throw e
}
})()
}

Sırasıyla kodu inceleyecek olursak:

  • İlk olarak paketleri yükleriz.
  • ctypeSchema.ts dosyasından şemamızı çekerek kodumuzun içerisine ekleriz.
  • Zincir üzerinde oluşturmak istediğimiz CType'ın olup olmadığını kontrol ederiz.
  • Zincirde yoksa nasıl ekleyebileceğimizin kodunu yazarız.
  • Dosya tek başına çalıştırılacak olursa yapılacak Ctype işlemlerini yazarız.

Bu şekilde zincirin içerisinde oluşturacağımız CType'ın olup olmadığını inceleyen ve yoksa oluşturan bir kod yazdık.

unutmayın

Zincir üzerine eklemek için bir deposito ödememiz gerekmektedir. Bu nedenle PILT Coinlere ihtiyacımız var unutmayalım.

Çalıştırma

Kodumuzu çalıştırmak için terminalde kilt-rocks klasöründe olduğumuzdan emin olduktan sonra şu kodu çalıştırabiliriz:

yarn ts-node attester/generateCtype.ts
Sırada Ne Var?

Eveeeet şimdi, artık Ctype'ı da oluşturduğumuza göre bizden bir attestation isteyecek Claimer bireyine ihtiyacımız var.