İçeriğe geç
academia.sh

Ders 09 / 12

Köken Bilgisi

Yapının nerede ve nasıl üretildiğini anlatan belge alan alan kurulur ve tek bir sayıya indirgenir: on dört alanın kaçı bağımsız olarak doğrulanabiliyor, kaçı yalnız beyan olarak kalıyor, yeniden üretim kaç alanı kanıta çeviriyor ve doğrulama eşiği yükseldikçe hattan kaç saniye gidiyor.

İçindekiler

Önceki ders imzanın kapsadığı alan ile doğrulayıcının sınayabildiği alanı ayırdı: beyan dokuz alana çıktığında imza dokuzunu da kapsıyordu, ama doğrulayıcı yalnız birini yeniden hesaplayabiliyordu. Kalan sekiz alan imzalanmış olarak geçiyordu ve imzalı olmak onları doğru yapmıyordu.

Bu ders o sekiz alanın yerine geçen belgeyi kurar: yapının nerede ve nasıl üretildiğini anlatan köken bilgisi. Ölçü tek bir sayıdır — belgenin kaç alanı bağımsız olarak doğrulanabiliyor, kaçı yalnız beyan olarak kalıyor. Bir alan, doğrulayanın kendi elde edebildiği bir nesneden yeniden hesaplanabiliyorsa kanıttır; hesaplanamıyorsa beyandır ve doğruluğu onu yazana güvenmeye kalır.

TZ11. Köken belgesi dört öbekte on dört alandır: hangi kaynak, hangi işlem, hangi ortam, hangi girdi. Belge ve nesneler node ile modellenir. TZ12. Doğrulayıcının bağımsız elde edebildiği nesne kümesi dörttür: kaynak ağacı, yapı tanımı dosyası, bağımlılık kilit dosyası ve yapı çıktısının baytları.

Belgenin On Dört Alanı

// olcum-agi/koken.mjs — koken belgesi alan alan kurulur: kaci bagimsiz dogrulanabiliyor
import { createHash } from "node:crypto";

const ozet = (b) => createHash("sha256").update(b).digest("hex").slice(0, 12);

// Kurgu bagimsiz nesneler: dogrulayici bunlari kendi elde edebilir ve yeniden ozetleyebilir.
const KAYNAK = Buffer.from(["ana.js", "olcum.js", "ayar.json"]
  .map((y) => `${y}\n// kurgu abone portali\n`).join(""));
const YAPI_TANIMI = Buffer.from("adim: derle, sina, paketle, imzala\n");
const KILIT = Buffer.from(Array.from({ length: 73 }, (_, i) => `bilesen-${i}@2.0`).join("\n"));
const CIKTI = Buffer.concat([Buffer.from("abone-portali\n"), Buffer.alloc(16384, "u")]);
const ELDEKI = { kaynak: KAYNAK, "yapi-tanimi": YAPI_TANIMI, kilit: KILIT, cikti: CIKTI };

// Koken belgesi: dort obek, on dort alan. `yazilan` belgeye konan deger.
const BELGE = [
  ["kaynak", "depo", "abone-portali", false],
  ["kaynak", "isleme", ozet(KAYNAK), true],
  ["kaynak", "dal", "ana", false],
  ["islem", "yapi-tanimi", ozet(YAPI_TANIMI), true],
  ["islem", "adim-listesi", "derle, sina, paketle, imzala", false],
  ["islem", "cagri-parametresi", "hedef=uretim", false],
  ["ortam", "calistirici-turu", "yalitilmis-kap", false],
  ["ortam", "temel-imaj", "7ad3e1c95006", false],
  ["ortam", "yalitim-duzeyi", "is basina yeni calistirici", false],
  ["ortam", "ag-erisimi", "kapali", false],
  ["girdi", "kilit", ozet(KILIT), true],
  ["girdi", "ortam-degiskeni-adlari", "HEDEF, SURUM", false],
  ["girdi", "onbellek-anahtari", "b41c-2", false],
  ["cikti", "cikti", ozet(CIKTI), true],
];

// Bir alan ancak elde edilebilir bir nesneden yeniden hesaplanabiliyorsa kanittir.
const S = [8, 24, 29, 0];
const satir = (s) => console.log(s.map((v, i) => String(v).padEnd(S[i])).join(""));
satir(["obek", "alan", "dogrulama yolu", "tur"]);
let kanit = 0;
for (const [obek, alan, yazilan, hesaplanir] of BELGE) {
  if (hesaplanir) kanit++;
  satir([obek, alan, hesaplanir ? "nesne yeniden ozetlenir" : "karsilastirilacak nesne yok",
    hesaplanir ? "kanit" : "beyan"]);
}
console.log("");
console.log(`belge ${BELGE.length} alan: ${kanit} kanit, ${BELGE.length - kanit} beyan`);

// Bes alana kasten yanlis deger yazilir; dogrulayici elindeki nesnelerle sinar.
const YANLIS = { isleme: "0000deadbeef", "yapi-tanimi": "111122223333",
  "temel-imaj": "999988887777", "yalitim-duzeyi": "paylasilan calistirici", cikti: "aaaabbbbcccc" };
const anahtar = { isleme: "kaynak", "yapi-tanimi": "yapi-tanimi", kilit: "kilit", cikti: "cikti" };
let yakalanan = 0;
for (const [, alan, , hesaplanir] of BELGE) {
  if (!(alan in YANLIS)) continue;
  if (hesaplanir && ozet(ELDEKI[anahtar[alan]]) !== YANLIS[alan]) yakalanan++;
}
console.log(`kasten yanlis yazilan ${Object.keys(YANLIS).length} alanin ${yakalanan} tanesi ` +
  `yakalandi, ${Object.keys(YANLIS).length - yakalanan} tanesi beyan oldugu icin sinanmadi`);
obek    alan                    dogrulama yolu               tur
kaynak  depo                    karsilastirilacak nesne yok  beyan
kaynak  isleme                  nesne yeniden ozetlenir      kanit
kaynak  dal                     karsilastirilacak nesne yok  beyan
islem   yapi-tanimi             nesne yeniden ozetlenir      kanit
islem   adim-listesi            karsilastirilacak nesne yok  beyan
islem   cagri-parametresi       karsilastirilacak nesne yok  beyan
ortam   calistirici-turu        karsilastirilacak nesne yok  beyan
ortam   temel-imaj              karsilastirilacak nesne yok  beyan
ortam   yalitim-duzeyi          karsilastirilacak nesne yok  beyan
ortam   ag-erisimi              karsilastirilacak nesne yok  beyan
girdi   kilit                   nesne yeniden ozetlenir      kanit
girdi   ortam-degiskeni-adlari  karsilastirilacak nesne yok  beyan
girdi   onbellek-anahtari       karsilastirilacak nesne yok  beyan
cikti   cikti                   nesne yeniden ozetlenir      kanit

belge 14 alan: 4 kanit, 10 beyan
kasten yanlis yazilan 5 alanin 3 tanesi yakalandi, 2 tanesi beyan oldugu icin sinanmadi

Belge on dört alan taşır ve dördü kanıttır. Dördünün ortak özelliği şudur: hepsi bir nesnenin özetidir ve o nesne doğrulayanın elinde vardır. İşleme özeti kaynak ağacından, yapı tanımı özeti depodaki dosyadan, kilit özeti bağımlılık kilit dosyasından, çıktı özeti yapı çıktısının baytlarından yeniden hesaplanır. Belge yanlış yazsa bile bu dört alanda yalan tutmaz.

Kalan on alan beyandır ve ilginç olan, aralarında hiç önemsiz bir alan bulunmamasıdır. Yalıtım düzeyi, ağ erişimi, çalıştırıcı türü ve temel imaj — dördü de yapının güvenilirliğine dair en çok şey söyleyen alanlardır. Hiçbiri sınanamaz, çünkü hiçbirinin karşılığı doğrulayanın elde edebileceği bir nesne değildir. “Ağ erişimi kapalıydı” cümlesi yapıyı koşturan tarafın kendi hakkında verdiği bir ifadedir.

Son satır bu ayrımı sayıya çevirir: beş alana kasten yanlış değer yazıldığında üçü yakalanır, ikisi sınanmaz. Yakalanmayan ikisi temel imaj ve yalıtım düzeyidir. Belgede “iş başına yeni çalıştırıcı” yazar, gerçekte paylaşılan çalıştırıcı kullanılmıştır ve hiçbir doğrulama bunu görmez. Bir köken belgesinin değeri alan sayısıyla değil, kanıt olan alan sayısıyla ölçülür.

Yeniden Üretim Neyi Kanıta Çevirir

On beyan alanının bir bölümü aslında çıktıya girer: adım listesi, çağrı parametresi ve temel imaj farklı olsaydı çıktı da farklı olurdu. Bu, sınanabilirlik için bir kaldıraç sunar — aynı bildirilen girdilerle yapı yeniden koşturulur ve çıktı aynı çıkarsa bildirim doğrulanmış olur.

TZ13. Yapı işlevi kurgudur ve bildirilen girdilerden çıktı üretir. On iki yapının üçünde bildirilmemiş bir girdi çıktıya girer, birinde çıktı sonradan değiştirilmiştir; tohum 410277 görünürdür.

// olcum-agi/yeniden-uretim.mjs — yeniden uretim hangi alani kanita cevirir
import { createHash } from "node:crypto";

const ozet = (b) => createHash("sha256").update(b).digest("hex").slice(0, 12);
// Kurgu yapi islevi: bildirilen girdilerden cikti uretir. Gizli girdi varsa ciktiya o da girer.
const yap = (g) => Buffer.from([g.kaynak, g.kilit, g.adimlar, g.parametre, g.temelImaj,
  g.gizli ?? ""].join("|"));

const uretec = (tohum) => () =>
  (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;
const r = uretec(410277);                                  // tohum gorunur

// On iki kurgu yapi. Uc tanesinde bildirilmemis girdi var, birinde cikti sonradan degistirildi.
const GIZLI = [3, 7, 11], DEGISTIRILEN = 9;
const YAPI = Array.from({ length: 12 }, (_, i) => {
  const no = i + 1;
  const girdi = { kaynak: `kaynak-${no}`, kilit: `kilit-${no}`, adimlar: "derle,sina,paketle",
    parametre: "hedef=uretim", temelImaj: no % 2 ? "temel-a" : "temel-b" };
  const gercek = yap(GIZLI.includes(no) ? { ...girdi, gizli: `kosum-${Math.floor(r() * 900)}` } : girdi);
  const beyanEdilen = no === DEGISTIRILEN ? ozet(Buffer.from("degistirilmis")) : ozet(gercek);
  return { no, girdi, beyanEdilen, gizliVar: GIZLI.includes(no) };
});

const S = [7, 16, 18, 12, 0];
const satir = (s) => console.log(s.map((v, i) => String(v).padEnd(S[i])).join(""));
satir(["yapi", "beyan edilen", "yeniden uretilen", "eslesme", "sebep"]);
let eslesen = 0, gercekBulgu = 0, yanlisIsaret = 0;
for (const y of YAPI) {
  const tekrar = ozet(yap(y.girdi));                       // yalniz BILDIRILEN girdilerle
  const esit = tekrar === y.beyanEdilen;
  if (esit) eslesen++;
  else if (y.gizliVar) yanlisIsaret++;
  else gercekBulgu++;
  if (y.no <= 4 || !esit)
    satir([y.no, y.beyanEdilen, tekrar, esit ? "evet" : "HAYIR",
      esit ? "-" : (y.gizliVar ? "bildirilmemis girdi" : "cikti degistirilmis")]);
}
console.log("");
console.log(`on iki yapinin ${eslesen}'i yeniden uretimde eslesiyor, ` +
  `${YAPI.length - eslesen} tanesi eslesmiyor: ${gercekBulgu} gercek, ${yanlisIsaret} yanlis isaret`);

// Yeniden uretim, ciktiya giren her bildirilen girdiyi sinanabilir kilar.
const CIKTIYA_GIREN = ["adim-listesi", "cagri-parametresi", "temel-imaj"];
const ONCE = 4, ALAN = 14;
console.log(`kanit alani ${ONCE}/${ALAN} -> ${ONCE + CIKTIYA_GIREN.length}/${ALAN}; ` +
  `sinanabilir hale gelen: ${CIKTIYA_GIREN.join(", ")}`);
console.log(`beyan olarak kalan ${ALAN - ONCE - CIKTIYA_GIREN.length}: ` +
  `depo, dal, calistirici-turu, yalitim-duzeyi, ag-erisimi, ortam-degiskeni-adlari, onbellek-anahtari`);
yapi   beyan edilen    yeniden uretilen  eslesme     sebep
1      bf07d2a43010    bf07d2a43010      evet        -
2      1ddced3cf18e    1ddced3cf18e      evet        -
3      e8ef828e21d6    708285ad34af      HAYIR       bildirilmemis girdi
4      ec17c7d09dca    ec17c7d09dca      evet        -
7      02dfd006731d    7837452fb129      HAYIR       bildirilmemis girdi
9      3dfd53002487    9c98f23fe16b      HAYIR       cikti degistirilmis
11     1e1126a5aff6    1f5be23c2504      HAYIR       bildirilmemis girdi

on iki yapinin 8'i yeniden uretimde eslesiyor, 4 tanesi eslesmiyor: 1 gercek, 3 yanlis isaret
kanit alani 4/14 -> 7/14; sinanabilir hale gelen: adim-listesi, cagri-parametresi, temel-imaj
beyan olarak kalan 7: depo, dal, calistirici-turu, yalitim-duzeyi, ag-erisimi, ortam-degiskeni-adlari, onbellek-anahtari

Yeniden üretim kanıt alanını 4’ten 7’ye çıkarır. Kazanılan üç alanın hepsi çıktıya giren girdilerdir: adım listesi, çağrı parametresi ve temel imaj yanlış yazılsaydı yeniden üretilen çıktı tutmazdı. Kalan yedi alan hiçbir koşulda sınanabilir hale gelmez, çünkü çıktıya hiç girmezler. Dal adı, çalıştırıcı türü, yalıtım düzeyi ve önbellek anahtarı üretilen baytları etkilemez; bir şeyi etkilemeyen bildirim de o şeyden geri okunamaz. Belgenin yarısı beyan olarak kalır ve bu bir eksiklik değil, yöntemin sınırıdır.

Ortadaki iki sayı ise kaldıracın bedelidir. On iki yapının dördü eşleşmez ve dördünden yalnız biri gerçektir; üçünde çıktıya bildirilmemiş bir girdi karışmıştır — koşum numarası, üretim anı, çalıştırıcı adı gibi bir değer. Bu üçünde yapı doğrudur, belge doğrudur, değişen tek şey ilan edilmemiş bir girdinin çıktıya sızmasıdır. Yanlış işaret oranı %75’tir ve bu oran taramanın işe yaramadığı durumun tam tanımıdır: dört uyarının üçü boşuna incelenirse dördüncüsü de aynı işaretin altında kalır.

Yanlış işaretin kaynağı da yöntemin kendisindedir. Yeniden üretim, bildirilen girdi kümesinin eksiksiz olduğunu varsayar; eksikse fark çıktıda görünür ama farkın nedeni belgede yazmaz. Eşleşmeyen bir yapının hangi sınıfa girdiğini anlamak için çıktı baytları karşılaştırılır ve sızan değer elle bulunur — bu, uyarı başına ayrı bir inceleme demektir. Üç yanlış işaretin üçü de düzeltilebilir kusurlardır; düzeltmenin yolu belgeye alan eklemek değil, o değeri çıktıdan çıkarmaktır. Kaldıracın kullanılabilir olması için yapının önce ilan edilmemiş girdiden arındırılması gerekir ve bu iş kökene değil, yapı tanımına aittir.

Eşik Yükseldikçe

Üç ölçüm bir politika sorusunu doğurur: dağıtımdan önce hangi eşik aranmalı?

TZ14. Kırk kurgu dağıtım isteği vardır; bozuk istekler de geçerli imza taşır — önceki dersin sonucudur, imza iddiayı kanıtlamaz. Köken üretimi 12 saniye, yeniden üretim 214 saniye olarak veri verilmiştir, ölçülmüş değildir; tohum 87344 görünürdür.

// olcum-agi/koken-esigi.mjs — dogrulama esigi yukseldikce gecen, bloke olan ve hattan giden sure
const uretec = (tohum) => () =>
  (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;
const r = uretec(87344);                                   // tohum gorunur

// Bozuk istek de gecerli imza tasir: onceki dersin sonucu — imza iddiayi kanitlamaz.
const ISTEK = Array.from({ length: 40 }, () => {
  const bozuk = r() < 0.12;
  return { bozuk, imzali: true, kokenVar: bozuk || r() < 0.85,
    kanitUyuyor: !bozuk, gizliGirdi: r() < 0.18 };         // gizli girdi: yeniden uretim eslesmez
});

// Sureler VERI olarak verilmistir, olculmus degil: koken uretimi 12 s, yeniden uretim 214 s.
const KOKEN_S = 12, TEKRAR_S = 214;
const ESIK = [
  ["imza yeter", (i) => i.imzali, 0],
  ["imza + koken belgesi", (i) => i.imzali && i.kokenVar, KOKEN_S],
  ["imza + dort kanit alani", (i) => i.imzali && i.kokenVar && i.kanitUyuyor, KOKEN_S],
  ["imza + yeniden uretim", (i) => i.imzali && i.kokenVar && i.kanitUyuyor && !i.gizliGirdi,
    KOKEN_S + TEKRAR_S],
];

const BOZUK = ISTEK.filter((i) => i.bozuk).length;
const S = [26, 9, 9, 14, 0];
const satir = (s) => console.log(s.map((v, i) => String(v).padEnd(S[i])).join(""));
satir(["esik", "gecen", "bloke", "yanlis bloke", "kacan bozuk / hat suresi"]);
for (const [ad, kural, sure] of ESIK) {
  const gecen = ISTEK.filter(kural);
  const bloke = ISTEK.filter((i) => !kural(i));
  satir([ad, gecen.length, bloke.length, bloke.filter((i) => !i.bozuk).length,
    `${gecen.filter((i) => i.bozuk).length} / ${sure * ISTEK.length} s`]);
}
console.log("");
console.log(`istek ${ISTEK.length}, gercekten bozuk ${BOZUK}, ` +
  `bildirilmemis girdi tasiyan ${ISTEK.filter((i) => i.gizliGirdi).length}, ` +
  `koken belgesi olmayan ${ISTEK.filter((i) => !i.kokenVar).length}; tohum 87344`);
esik                      gecen    bloke    yanlis bloke  kacan bozuk / hat suresi
imza yeter                40       0        0             4 / 0 s
imza + koken belgesi      35       5        5             4 / 480 s
imza + dort kanit alani   31       9        5             0 / 480 s
imza + yeniden uretim     26       14       10            0 / 9040 s

istek 40, gercekten bozuk 4, bildirilmemis girdi tasiyan 7, koken belgesi olmayan 5; tohum 87344

İkinci satır bu kursun en sık karşılaşılan yanılgısını sayıya çevirir. Köken belgesinin varlığını aramak dört bozuk isteğin dördünü de geçirir — belge bozuk isteklerde de vardır, çünkü belgeyi üreten yapının kendisidir. Karşılığında hattan 480 saniye gider ve beş meşru istek yanlış yere bloke olur. Marjinal değeri sıfır olan bir kapı budur: bir alanı dolduran, hiçbir şeyi karşılaştırmayan bir aşama.

Üçüncü satır aynı 480 saniyeyle dört bozuk isteğin dördünü de tutar. Aradaki fark tek bir işlemdir: belgenin dört kanıt alanı, doğrulayanın kendi elde ettiği nesnelerle karşılaştırılır. Yanlış bloke sayısı değişmez, kaçan bozuk 4’ten 0’a iner. Köken belgesinin değeri üretilmesinde değil, karşılaştırılmasındadır.

Dördüncü satır kaldıracın fiyatını gösterir. Yeniden üretim hiçbir yeni bozuk isteği tutmaz — dördü zaten üçüncü satırda tutulmuştu — ama hat süresini 480 saniyeden 9.040 saniyeye çıkarır ve yanlış bloke sayısını 5’ten 10’a, yani kırk isteğin dörtte birine yükseltir. Kanıt alanını 7’ye çıkarmanın karşılığı budur ve karşılığın ödenip ödenmeyeceği kaçan bozuk sayısına bakılarak karar verilir, alan sayısına bakılarak değil. Dört isteğinden birinin boşuna durduğu bir eşik, eninde sonunda atlanan bir eşiktir.

Özet

  • Köken belgesi dört öbekte on dört alandır; 4 alan kanıt, 10 alan beyandır. Kanıt olanların ortak özelliği, doğrulayanın elindeki bir nesnenin özeti olmalarıdır.
  • Beyan kalan on alan arasında önemsiz alan yoktur: yalıtım düzeyi, ağ erişimi, çalıştırıcı türü ve temel imaj sınanamaz. Kasten yanlış yazılan beş alanın 3’ü yakalanır, 2’si sınanmaz.
  • Yeniden üretim kanıt alanını 4’ten 7’ye çıkarır; kazanılan üç alan çıktıya giren girdilerdir. Kalan 7 alan hiçbir koşulda sınanamaz, çünkü üretilen baytları etkilemez.
  • On iki yapının 4’ü yeniden üretimde eşleşmez ve yalnız 1’i gerçektir; yanlış işaret oranı %75’tir.
  • Köken belgesinin varlığını aramak 4 bozuk isteğin 4’ünü de geçirir ve 480 saniye alır; aynı süreyle dört kanıt alanını karşılaştırmak kaçan bozuğu 0’a indirir. Yeniden üretim eşiği hiçbir yeni bozuk tutmaz, hat süresini 9.040 saniyeye ve yanlış blokeyi 10’a çıkarır.

Sonraki Adım

Köken belgesi kuruldu, kanıt ile beyan ayrıldı ve eşik yükseltmenin fiyatı yazıldı. Ortada duran şey yedi beyan alanıdır ve bunların dördü doğrudan tek bir konuyu anlatır: yapının hangi ortamda koştuğunu. Çalıştırıcı türü, yalıtım düzeyi, ağ erişimi ve ortam değişkeni adları belgede yazar, hiçbiri sınanamaz — ve sınanamadıkları için değerleri yalnız o ortamın gerçekten öyle kurulmuş olmasına bağlıdır.

Sonraki ders o ortamı kalem kalem sayar. Ölçü artık belgenin alanı değil, derleme ortamının kendi yetkisidir: hat kaç sırra erişiyor, kaçı gerçekten gerekiyor, ağ erişimi kapatıldığında kaç adım kırılıyor ve dış katkıdan gelen bir değişiklik koştuğunda kaç sır açığa çıkabiliyor?

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat