FlowCards: Ergo dApp Geliştirme için Deklaratif Bir Çerçeve
29 Nisan 2020

Taslağın düzenlenmesi için Robert Kornacki 'ye teşekkürler.
Giriş
ErgoScript, Ergo blok zinciri tarafından kullanılan akıllı sözleşme dilidir. Scala/Kotlin'den alınan özlü bir sözdizimine sahip olmasına rağmen, kavramsal olarak ErgoScript, hepimizin bildiği ve sevdiği geleneksel dillere göre oldukça farklı olduğu için başlangıçta kafa karıştırıcı görünebilir. Bunun nedeni, Ergo'nun bir UTXO tabanlı blok zinciri olmasıdır, oysa akıllı sözleşmeler geleneksel olarak Ethereum gibi hesap tabanlı sistemlerle ilişkilendirilir. Ancak, Ergo'nun işlem modeli, hesap tabanlı modele göre birçok avantaja sahiptir ve doğru bir yaklaşımla, Ergo sözleşmelerini geliştirmek, Solidity kodu yazmaktan ve hata ayıklamaktan çok daha kolay olabilir.
Aşağıda, Ergo sözleşme modelini farklı kılan temel yönleri ele alacağız:
Paradigma
Ethereum'un hesap modeli zorlayıcıdır. Bu, Alice'ten Bob'a para göndermenin tipik görevlerinin, depolamadaki bakiyeleri bir dizi işlem olarak değiştirmeyi gerektirdiği anlamına gelir. Öte yandan, Ergo'nun UTXO tabanlı programlama modeli deklaratiftir. ErgoScript sözleşmeleri, bir işlemin blok zinciri tarafından kabul edilmesi için gereken koşulları belirtir (sözleşme yürütülmesi sonucunda depolama durumunda yapılacak değişiklikler değil).
Ölçeklenebilirlik
Ethereum'un hesap modelinde hem depolama değişiklikleri hem de geçerlilik kontrolleri, kod yürütülmesi sırasında on-chain gerçekleştirilir. Buna karşılık, Ergo işlemleri off-chain oluşturulur ve yalnızca geçerlilik kontrolleri on-chain gerçekleştirilir, böylece ağdaki her düğüm tarafından gerçekleştirilen işlem sayısını azaltır. Ayrıca, işlem grafiğinin değişmezliği nedeniyle, ağdaki işlem başına verimliliği artırmak için çeşitli optimizasyon stratejileri mümkündür. Ayrıca, hafif doğrulayıcı düğümler de mümkündür, böylece ağın ölçeklenebilirliği ve erişilebilirliği daha da kolaylaşır.
Paylaşılan durum
Hesap tabanlı model, karmaşık anlamsalara (ve ince milyon dolarlık hatalara) yol açtığı bilinen paylaşılan değişken duruma dayanır. Ergo'nun modeli, değişmez bir işlem grafiğine dayanır. Bu yaklaşım, Bitcoin'den miras alınmıştır ve blok zincirlerinin eşzamanlı ve dağıtık doğasıyla iyi çalışır ve hafif güvenilir istemcileri kolaylaştırır.
İfade Gücü
Ethereum, blok zincirinde Turing-tamamlayıcı bir dilin yürütülmesini savunmuştur. Teorik olarak sınırsız potansiyel vaat etmesine rağmen, pratikte aşırı blok zinciri şişkinliğinden, ince milyon dolarlık hatalardan, sözleşme karmaşıklığını sınırlayan gaz maliyetlerinden ve diğer benzeri sorunlardan ciddi sınırlamalar ortaya çıkmıştır. Ergo ise, UTXO'yu genişleterek Turing-tamamlayıcılığı sağlarken, ErgoScript dilinin karmaşıklığını sınırlamaktadır. Aynı ifade gücü, farklı ve daha anlamsal olarak sağlam bir şekilde elde edilir.
Yukarıdaki tüm noktalarla, Ergo'nun kullandığı modelin birçok faydası olduğu açık olmalıdır. Bu makalenin geri kalanında, karmaşık Ergo sözleşmelerini deklaratif ve görsel bir şekilde tasarlamaya olanak tanıyan bir dApp geliştirici bileşeni olan FlowCards kavramını tanıtacağım.
Zorlayıcıdan Deklaratife
Ethereum'un zorlayıcı programlama modelinde bir işlem, Ethereum VM tarafından yürütülen bir dizi işlemdir. Aşağıdaki Solidity fonksiyonu, gönderen'den alıcıya token transferini uygular. İşlem, gönderen bu fonksiyonu bir sözleşme örneği üzerinde çağırdığında başlar ve fonksiyon döndüğünde sona erer.
// Herhangi bir çağrıcıdan bir adrese mevcut coin miktarını gönderir
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Yetersiz bakiye.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
Fonksiyon önce ön koşulları kontrol eder, ardından depolamayı (yani bakiyeleri) günceller ve nihayetinde Sent olayı olarak son koşulu yayınlar. İşlem tarafından tüketilen gaz, bu işlemi yürüttüğü için madenciye ödül olarak gönderilir.
Ethereum'dan farklı olarak, Ergo'daki bir işlem, harcadığı bir listeyi tutan bir veri yapısıdır ve toplam ERG ve token bakiyelerini koruyarak oluşturduğu bir listeyi içerir (bu nedenle Ergo, Bitcoin'e benzer).
Yukarıdaki örneğe dönersek, Ergo yerel olarak token'ları desteklediğinden, bu belirli token gönderme örneği için ErgoScript'te herhangi bir kod yazmamıza gerek yoktur. Bunun yerine, aşağıdaki şekilde gösterilen 'send' işlemini oluşturmamız gerekir; bu, aynı token transferini ancak deklaratif olarak tanımlar.

Resim, ağ kullanıcısının gerçekleştirmesi gereken aşağıdaki adımları görsel olarak tanımlar:
- Toplamda
tB >= amounttoken veB >= txFee + minErgERG içeren harcanmamış gönderen kutularını seçin. receiverkamu anahtarı ile korunantargetkutusunuminErgERG veamountTtoken ile oluşturun.txFeeERG ileminerFeesözleşmesi tarafından korunan bir ücret çıktısı oluşturun.senderkamu anahtarı ile korunan bir değişim çıktısı oluşturun; bu,B - minErg - txFeeERG vetB - amountTtoken içerir.- Yeni bir işlem oluşturun, gönderenin özel anahtarı ile imzalayın ve Ergo ağına gönderin.
Burada önemli olan, bu adımların tamamının off-chain (örneğin Appkit İşlem API'si kullanarak) kullanıcının uygulaması tarafından gerçekleştirildiğidir. Ergo ağ düğümleri, bu işlem oluşturma sürecini tekrarlamak zorunda değildir; yalnızca zaten oluşturulmuş işlemi doğrulamaları gerekir. ErgoScript sözleşmeleri, işlemin girdilerinde saklanır ve harcama koşullarını kontrol eder. Düğüm, işlem doğrulandığında sözleşmeleri on-chain yürütür. İşlem, tüm koşullar yerine getirildiğinde geçerlidir.
Böylece, Ethereum'da "gönderen'den alıcıya miktar gönderdiğimizde", kelimenin tam anlamıyla bakiyeleri düzenliyor ve depolamayı belirli bir komut seti ile güncelliyoruz. Bu, on-chain gerçekleşir ve dolayısıyla bu süreç sonucunda yeni bir işlem de on-chain oluşturulur.
Ergo'da (Bitcoin'de olduğu gibi) işlemler off-chain oluşturulur ve ağ düğümleri yalnızca bunları doğrular. İşlemin blok zinciri durumundaki etkisi, giriş coin'lerinin (veya Ergo'nun terimiyle Kutuların) kaldırılması ve çıkış kutularının UTXO setine eklenmesidir.
Yukarıdaki örnekte ErgoScript sözleşmesi kullanmıyoruz, bunun yerine harcama ön koşulu olarak bir imza kontrolü kullanıldığını varsayıyoruz. Ancak daha karmaşık uygulama senaryolarında, elbette ErgoScript kullanmamız gerekecek; bu, bir sonraki tartışacağımız konudur.
Durumu Değiştirmekten Bağlamı Kontrol Etmeye
send fonksiyonu örneğinde önce ön koşulu kontrol ettik (require(amount <= balances[msg.sender],...)) ve ardından durumu değiştirdik (yani bakiyeleri güncelledik balances[msg.sender] -= amount). Bu, Ethereum işlemlerinde tipiktir. Bir şeyi değiştirmeden önce, bunu yapmanın geçerli olup olmadığını kontrol etmemiz gerekir.
Ergo'da, daha önce tartıştığımız gibi, durum (yani UTXO kutularının seti), geçerli bir işlem bir bloğa dahil edildiğinde dolaylı olarak değiştirilir. Bu nedenle, işlem bloğa eklenmeden önce yalnızca ön koşulları kontrol etmemiz gerekir. İşte ErgoScript sözleşmelerinin yaptığı budur.
ErgoScript'te "durumu değiştirmek" mümkün değildir çünkü bu, coin harcama için ön koşulları kontrol etmek üzere bir dildir. ErgoScript, yan etkisi olmayan, değişmez veri değerleri üzerinde çalışan tamamen işlevsel bir dildir. Bu, bir betikte mevcut olan tüm girdilerin, çıktının ve diğer işlem parametrelerinin değişmez olduğu anlamına gelir. Bu, ErgoScript'i öğrenmesi kolay ve kullanması güvenli bir dil haline getiren diğer şeylerin yanı sıra.
Bitcoin'e benzer şekilde, her giriş kutusu, kutunun harcama izinlerini kontrol etmek için true değerini döndürmesi gereken bir betik içerir (yani UTXO setinden kaldırmak ve işlemi bloğa eklemek için).
Eğer titiz olursak, ErgoScript'i Ergo sözleşmelerinin dili olarak düşünmek yanlıştır (katı anlamda), çünkü bu, kutuları "yasadışı" harcamalardan koruyan önermelerin (mantıksal yargılar, formüller vb.) dilidir. Bitcoin'in aksine, Ergo'da tüm işlem ve mevcut blok zinciri bağlamının bir kısmı her betiğe açıktır. Bu nedenle, her betik, işlemin oluşturduğu çıktıları, bunların ERG ve token miktarlarını (örneğin, örnek DEX sözleşmelerimizde bu yeteneği kullanacağız), mevcut blok numarasını vb. kontrol edebilir.
ErgoScript'te, belirli bir bağlamda değişikliklerin (yani coin harcama) olup olmayacağını tanımlarsınız. Bu, bir sözleşmenin kodunda değişiklikleri zorlayıcı bir şekilde programlamanın aksinedir.
Ergo'nun işlem modeli, (DEX, DeFi Uygulamaları, LETS vb.) gibi birçok uygulama yelpazesini açar, ancak sözleşmeleri doğrudan coin harcama için ön koşullar olarak tasarlamak sezgisel değildir. Bir sonraki bölümlerde, FlowCard Diyagramları kullanarak sözleşmeleri deklaratif olarak tasarlamak için yararlı bir grafik notasyonunu ele alacağız; bu, yürütülebilir bileşenlerin (FlowCards) görsel bir temsilidir.
FlowCards, Ergo platformunda dApp geliştirmeyi köklü bir şekilde basitleştirmeyi amaçlamaktadır; yüksek seviyeli bir deklaratif dil, yürütme çalışma zamanı, depolama formatı ve grafik notasyon sunarak.
Yüksek seviyeli diyagramlarla başlayacağız ve FlowCard spesifikasyonuna inerek devam edeceğiz.
FlowCard Diyagramları
FlowCard diyagramlarının arkasındaki fikir, aşağıdaki gözlemlere dayanmaktadır: 1) Bir Ergo kutusu değişmezdir ve yalnızca onu bir girdi olarak kullanan işlemde harcanabilir. 2) Bu nedenle, kutuların işlemler aracılığıyla akışını çizebiliriz, böylece işlemin içine akış yapan kutular harcanır ve dışarı akış yapan kutular oluşturulur ve UTXO'ya eklenir. 3) Bu perspektiften bir işlem, ERG ve token bakiyelerini koruyarak eski kutuları yeni kutulara dönüştüren bir dönüştürücüden başka bir şey değildir.
Aşağıdaki şekil, daha önce gördüğümüz Ergo işleminin ana unsurlarını göstermektedir (şimdi FlowCard Diyagramı adı altında).

Diagramın her bir öğesi arkasında kesin bir anlam (anlam) vardır, böylece diagram, temel yürütülebilir bileşenin (FlowCard olarak adlandırılır) görsel bir temsilidir.
FlowCard, Ergo dApp'inde işlemi oluşturmak ve başlatmak için yeniden kullanılabilir bir bileşen olarak kullanılabilir. Bunu gelecek bölümlerde tartışacağız.
Şimdi FlowCard diyagramının bireysel parçalarına birer birer bakalım.
1. İsim ve Parametreler
Her akış kartına bir isim ve bir dizi tipli parametre verilir. Bu, parametrelerle bir şablona benzer. Yukarıdaki şekilde, beş parametreye sahip Send akış kartını görebiliriz. Parametreler, spesifikasyonda kullanılır.
2. Sözleşme Cüzdanı
Bu, akış kartının ana unsurlarından biridir. Her kutunun bir koruma betiği vardır. Genellikle, bu, bir imzayı bir kamu anahtarı ile kontrol eden betiktir. Bu betik, ErgoScript'te basittir ve def pk(pubkey: Address) = { pubkey } şablonu gibi tanımlanır; burada pubkey, Address türünde bir parametredir. Şekilde, betik şablonu pk(sender) parametresine uygulanır ve böylece somut bir cüzdan sözleşmesi elde edilir. Bu nedenle, pk(sender) ve pk(receiver) farklı betikler üretir ve diyagramda farklı cüzdanları temsil eder, her ne kadar aynı şablonu kullansalar da.
Sözleşme Cüzdanı, belirli bir betikten türetilmiş tüm UTXO kutularının bir setini içerir. Örneğin, şekil, şablonun pk olduğu ve pubkey parametresinin sender akış kartı parametresi ile değiştirildiği durumu göstermektedir.
3. Sözleşme
Bir sözleşme bir kutunun özelliği olmasına rağmen, diyagramda kutuları sözleşmelerine göre gruplandırırız; bu nedenle kutuların sözleşmelere ait olduğu, sözleşmelerin kutulara ait olduğu gibi görünür. Örneğin, üç örneklenmiş sözleşmemiz vardır: pk(sender), pk(receiver) ve minerFee. Not edin ki, pk(sender), sender somut parametresi ile pk şablonunun örneğidir ve minerFee, madenci ödül kutularını koruyan önceden tanımlanmış sözleşmenin örneğidir.
4. Kutunun adı
Diyagramda her kutuya bir isim verebiliriz. Diyagramın okunabilirliğinin yanı sıra, ismi, sözleşmedeki kutuya daha karmaşık bir indeksli erişimin eşanlamlısı olarak da kullanırız. Örneğin, change, kutunun adı olup, OUTPUTS(2) yerine ErgoScript koşullarında da kullanılabilir. Ayrıca, kutu isimlerini harcama koşullarını kutularla ilişkilendirmek için de kullanırız.
5. Cüzdandaki Kutular
Diyagramda, kutuları (daha koyu dikdörtgenler) sözleşme cüzdanlarına (daha açık dikdörtgenler) ait olarak gösteriyoruz. Her böyle kutu dikdörtgeni, bir gri işlem dikdörtgeni ile ya turuncu ya da yeşil oklar veya her ikisiyle bağlantılıdır. Bir çıkış kutusu (gelen yeşil ok ile) birçok metin satırı içerebilir; her satır, işlemin bir parçası olarak kontrol edilmesi gereken bir koşulu belirtir. İlk satır, kutuda yer alması gereken ERG miktarına ilişkin koşulu belirtir. Diğer satırlar aşağıdaki biçimlerden birini alabilir:
amount: TOKEN- kutu, verilenTOKENmiktarını içermelidir.R == value- kutu, verilenRkaydının verilenvaluedeğerini içermelidir.boxName ? condition-boxNameadlı kutu, betiğindeconditionkontrol etmelidir.
Bu koşulları aşağıdaki bölümlerde tartışacağız.
6. Kutudaki ERG Miktarı
Her kutu, minimum bir ERG miktarını saklamalıdır. Bu, oluşturulan işlemin doğrulanması sırasında kontrol edilir. Diyagramda ERG miktarı her zaman ilk satır olarak gösterilir (örneğin, B: ERG veya B - minErg - txFee). Değer türü ataması B: ERG isteğe bağlıdır ve okunabilirlik için kullanılabilir. Değer bir formül olarak verildiğinde, bu formül, kutuyu oluşturan işlem tarafından saygı gösterilmelidir.
Anlamak önemlidir ki, amount ve txFee gibi değişkenler kutuların adlandırılmış özellikleri değildir. Bunlar, tüm diyagramın parametreleridir ve bazı miktarları temsil eder. Başka bir deyişle, bunlar işlemler arasında paylaşılan parametrelerdir (örneğin, aşağıdaki DEX örneğinden Satış Emri ve Takas işlemleri tAmt parametresini paylaşır). Bu nedenle, aynı isim, diyagram boyunca aynı değere bağlıdır (bu, araçların çok yardımcı olacağı bir yerdir). Ancak, bu değerlerin on-chain doğrulaması söz konusu olduğunda, yalnızca ? ile işaretlenmiş açık koşullar ErgoScript'e dönüştürülür. Aynı zamanda, diğer tüm koşullar, işlem oluşturma sırasında (örneğin, Appkit API'sini kullanan bir uygulamada) ve blok zincirine eklendiğinde işlem doğrulaması sırasında off-chain sağlanır.
7. T token Miktarı
Bir kutu, birçok token değerini saklayabilir. Diyagramdaki token'lar adlandırılır ve value değişkeni value: T ifadesi kullanılarak token T ile ilişkilendirilebilir. value, formül ile verilebilir. Eğer formül, boxName ? formula gibi bir kutu adı ile başlıyorsa, o zaman bu da boxName kutusunun koruma betiğinde kontrol edilmelidir. Bu ek spesifikasyon çok kullanışlıdır çünkü 1) görsel tasarımı otomatik olarak doğrulamaya olanak tanır ve 2) bir diyagramdaki kutularda belirtilen koşullar, gerekli koruma betiklerini sentezlemek için yeterlidir. (bununla ilgili daha fazla bilgi "Diyagramlardan ErgoScript Sözleşmelerine" başlığında)
8. Tx Girdileri
Girdiler, ilgili işlemi turuncu oklarla bağlar. Bir girdi okunun aşağıdaki biçimlerde bir etiketi olabilir:
name@index- isteğe bağlı bir isim ile bir indeks, yanifee@0veya@2. Bu, okun hedef uç noktasının bir özelliğidir. İsim, ilgili kutuların koşullarında kullanılır veindex, işlemin INPUTS koleksiyonundaki ilgili kutunun konumudur.!action- okun kaynağının bir özelliğidir ve kutunun alternatif harcama yoluna bir isim verir (bunu DEX örneğinde göreceğiz).
Alternatif harcama yolları nedeniyle, bir kutunun birçok çıkış turuncu oku olabilir; bu durumda, her biri farklı eylemlerle etiketlenmelidir.
9. İşlem
Bir işlem, giriş kutularını harcar ve çıkış kutuları oluşturur. Giriş kutuları turuncu oklarla verilir ve etiketlerin, INPUTS koleksiyonundaki doğru indekslere girdi yerleştirmesi beklenir. Çıkış kutuları yeşil oklarla verilir. Her işlem, ERG değerlerinin (girdilerin toplamı == çıktının toplamı) ve her token için girdilerin toplamının >= çıktının toplamı olmasını sağlamalıdır. Tasarım diyagramı, tüm çıkış kutuları için ERG ve token değerlerinin açık bir şekilde belirtilmesini gerektirir, böylece örtük hatalardan kaçınılır ve daha iyi okunabilirlik sağlanır.
10. Tx Çıktıları
Çıktılar, ilgili işlemi yeşil oklarla bağlar. Bir çıkış okunun aşağıdaki biçimde bir etiketi olabilir: name@index, burada isteğe bağlı bir isim bir indeks ile birlikte gelir, yani fee@0 veya @2. Bu, okun kaynak uç noktasının bir özelliğidir. İsim, ilgili kutuların koşullarında kullanılır ve index, işlemin OUTPUTS koleksiyonundaki ilgili kutunun konumudur.
Örnek: Merkezi Olmayan Borsa (DEX)
Şimdi yukarıda tanımlanan notasyonu kullanarak bir DEX dApp için bir FlowCard tasarlayalım. Yeterince basit ama aynı zamanda FlowCard diyagramlarının tüm ana özelliklerini de göstermektedir.
dApp senaryosu aşağıdaki şekilde gösterilmektedir:
DEX dApp'inin üç katılımcısı (alıcı, satıcı ve DEX) vardır ve katılımcılar tarafından oluşturulan beş farklı işlem türü bulunmaktadır. Alıcı, ergAmt ERG'yi tAmt TID token ile değiştirmek istemektedir (veya tersine, satıcı TID token'larını ERG'ler için satmak istemektedir; ilk olarak siparişi gönderenin önemi yoktur). Hem alıcı hem de satıcı, siparişlerini istedikleri zaman iptal edebilirler. DEX'in off-chain eşleştirme hizmeti, eşleşen siparişleri bulabilir ve değişimi tamamlamak için Swap işlemini oluşturabilir.
Aşağıdaki diyagram, DEX dApp tarafından off-chain oluşturulması gereken beş işlemi tamamen (ve resmi olarak) belirtmektedir. Ayrıca, on-chain doğrulanması gereken tüm harcama koşullarını da belirtmektedir.

FlowCard diyagramını ve her işlemin mantığını detaylı olarak tartışalım:
Alım Emri İşlemi
Bir alıcı, Buy Order işlemi oluşturur. İşlem, pk(buyer) cüzdanındaki bir veya daha fazla kutudan E miktarında ERG'yi harcar. İşlem, buyOrder betiği ile korunan bid kutusunu oluşturur. buyOrder betiği, spesifikasyondan (aşağıda "Diyagramlardan ErgoScript Sözleşmelerine" başlığında) ya manuel olarak ya da otomatik olarak bir araç tarafından sentezlenir. Tasarım sırasında buyOrder betiğini açıkça tanımlamaya gerek olmasa da, çalışma zamanında bid kutusu, harcama koşullarını kontrol eden koruma önermesi olarak buyOrder betiğini içermelidir; aksi takdirde, diyagramda belirtilen koşullar kontrol edilmeyecektir.
change kutusu, işlemin giriş ve çıkış toplamlarını dengelemek için oluşturulur. İşlem ücreti kutusu, araçlar tarafından otomatik olarak eklenebileceği için atlanmıştır. Ancak pratikte, tasarımcı, diyagrama açıkça ücret kutusunu ekleyebilir. Bu, daha karmaşık işlemler (Takas gibi) için geçerlidir; burada işlem ücretini ödemenin birçok yolu vardır.
Alım İptali, Satış İptali İşlemleri
Herhangi bir zamanda, alıcı siparişi CancelBuy işlemi göndererek iptal edebilir. İşlem, bid kutusunu koruyan buyOrder sözleşmesini karşılamalıdır. Diyagramda görebileceğiniz gibi, hem Cancel hem de Swap işlemleri bid kutusunu harcayabilir. Bir kutunun harcama alternatifleri (veya harcama yolları) olduğunda, her alternatif, ! ile ön eklenmiş benzersiz bir isimle tanımlanır (!cancel ve !swap bid kutusu için). Her alternatif yolun belirli harcama koşulları vardır. Örneğimizde, Cancel Buy işlemi bid kutusunu harcadığında ?buyer koşulu karşılanmalıdır; bu, "buyer adresinin imzası işlemin içinde sunulmalıdır" şeklinde okunur. Bu nedenle, yalnızca alıcı, alım emrini iptal edebilir. Bu "imza" koşulu yalnızca !cancel alternatif harcama yolu için gereklidir ve !swap için gerekli değildir.
Satış Emri İşlemi
Sell Order işlemi, ERG'lerin yanı sıra token'larla da ilgilendiği için BuyOrder ile benzerdir. İşlem, satıcının cüzdanından (belirtilen pk(seller) sözleşmesi) E: ERG ve T: TID token'larını harcar. İki çıkış ask ve changedir. Değişim, işlemi dengelemek için standart bir kutudur. ask kutusu, değişim için tAmt: TID token'larını ve her kutuda gerekli minimum ERG miktarını (minErg: ERG) saklar.
Takas İşlemi
Bu, DEX dApp senaryosundaki ana işlemdir. İşlemin giriş kutularında birkaç harcama koşulu vardır ve bu koşullar buyOrder ve sellOrder betiklerinde yer alır (işlem blok zincirine eklendiğinde doğrulanır). Ancak, diyagramda bu koşullar bid ve ask kutularında belirtilmemiştir; bunun yerine, işlemin çıkış kutularında tanımlanmıştır.
Bu, kullanılabilirliği artırmak için bir konvansiyondur çünkü çoğu koşul çıkış kutularının özellikleri ile ilgilidir. Bu özellikleri bid kutusunda belirtebiliriz, ancak o zaman daha karmaşık ifadeler kullanmamız gerekecektir.
buyerOut@0 ile etiketlenmiş ok tarafından oluşturulan çıkışı düşünelim. Bu etiket, çıkışın işlemin OUTPUTS koleksiyonundaki 0 indeksinde olduğunu ve diyagramda bu kutuya buyerOut adıyla atıfta bulunabileceğimizi belirtir. Böylece, hem kutunun kendisine hem de okuna bir isim vermek için etiketleyebiliriz.
buyerOut kutusunda gösterilen koşullar, bid ? condition biçimindedir; bu, bid kutusunu harcamak için on-chain doğrulanmaları gerektiği anlamına gelir.
Koşulların anlamı şudur:
tAmt: TID, kutununtAmtmiktarındaTIDtoken'ına sahip olmasını gerektirir.R4 == bid.id, kutudaki R4 kaydınınbidkutusunun kimliğine eşit olmasını gerektirir.script == buyer,buyerOutkutusunun diyagramda bulunduğu cüzdanın betiğine sahip olmasını gerektirir; yanipk(buyer)
Benzer özellikler, 1 indeksinde belirtilen sellerOut kutusuna eklenir ve ismi kutunun kendisinde, okta değil, etiketle verilir.
Swap işlemi, bid ve ask kutularını !swap harcama yolu kullanarak harcar; ancak !cancel'dan farklı olarak, yoldaki koşullar belirtilmemiştir. İşte burada bid ? ve ask ? ön ekleri devreye girer. Bu, buyerOut ve sellerOut kutularında listelenen koşulların sırasıyla bid ve ask kutularının !swap harcama yoluna taşınması için kullanılır.
Çıkış kutularının koşullarına bakarsanız, bunların satıcı ve alıcının cüzdanları arasındaki değer değişimini tam olarak belirttiğini göreceksiniz. Alıcı, gerekli miktarda TID token'ını alır ve satıcı, karşılık gelen miktarda ERG alır. Swap işlemi, buyOrder ve sellOrder sözleşmeleri ile eşleşen iki kutu olduğunda oluşturulur.
Diyagramlardan ErgoScript Sözleşmelerine
FlowCard spesifikasyonlarının ilginç yanı, gerekli ErgoTree betiklerini otomatik olarak oluşturmak için kullanılabilmesidir. Uygun araç desteği ile bu otomatik olarak yapılabilir, ancak bunun eksikliğinde manuel olarak yapılabilir. Böylece, FlowCard, bir Ergo dApp'in tüm tasarım seçimlerini ve anlamsal ayrıntılarını yakalamamıza ve görsel olarak temsil etmemize olanak tanır.
Bir sonraki adımımız, DEX akış kartında verilen bilgilerden buyOrder sözleşmesini mekanik olarak oluşturmaktır.
Her betik, kutunun harcamasına izin vermek için true değerine değerlendirilmesi gereken bir önermedir (boolean değerli ifade). Aynı anda birçok koşulun karşılanması gerektiğinde, bunları AND ikili işlemi kullanarak mantıksal bir formülde birleştirebiliriz ve alternatiflerimiz (mutlaka dışlayıcı olmayan) olduğunda, bunları OR işlemi içine koyabiliriz.
buyOrder kutusunun alternatif harcama yolları !cancel ve !swap'dır. Bu nedenle, ErgoScript kodu, her harcama yolu için bir argümanla OR işlemi içermelidir.
/** buyOrder sözleşmesi */
{
val cancelCondition = {}
val swapCondition = {}
cancelCondition || swapCondition
}
cancelCondition ifadesinin formülü, buyOrder kutusunun !cancel harcama yolunda verilmektedir. Bunu doğrudan betiğe dahil edebiliriz.
/** buyOrder sözleşmesi */
{
val cancelCondition = { buyer }
val swapCondition = {}
cancelCondition || swapCondition
}
buyOrder kutusunun !swap harcama yolu için koşullar, Swap işleminin buyerOut çıkış kutusunda belirtilmiştir. Bunları basitçe swapCondition içine dahil edersek, sözdizimsel olarak hatalı bir betik elde ederiz.
/** buyOrder sözleşmesi */
{
val cancelCondition = { buyer }
val swapCondition = {
tAmt: TID &&
R4 == bid.id &&
@contract
}
cancelCondition || swapCondition
}
Ancak, diyagramdaki koşulları ErgoScript ifadelerine dönüştürmek için aşağıdaki basit kuralları kullanabiliriz:
buyerOut@0==>val buyerOut = OUTPUTS(0)tAmt: TID==>tid._2 == tAmtburadatid = buyerOut.tokens(TID)R4 == bid.id==>R4 == SELF.idburadaR4 = buyerOut.R4[Coll[Byte]].getscript == buyer==>buyerOut.propositionBytes == buyer.propBytes
Not: diyagramda TID, bir token kimliğini temsil eder, ancak ErgoScript, token'lara kimlikleri ile erişemez, bu nedenle tokens.getByKey(TID) yazamayız. Bu nedenle, diyagram ErgoScript'e dönüştürüldüğünde, TID, kutunun tokens koleksiyonundaki indeksin adlandırılmış sabiti haline gelir. Sabitin somut değeri, buyOrder kutusuyla birlikte BuyOrder işlemi oluşturulduğunda atanır. Somut tokenId, TID sabiti ve buyerOut kutusundaki gerçek token'lar arasındaki ilişki ve tutarlılık, FlowCard'ı kılavuz spesifikasyon olarak kullanan uygulama kodu tarafından off-chain sağlanır. Bu, çok karmaşık görünebilir, ancak bu, diyagram spesifikasyonundan gerçek yürütülebilir uygulama koduna geçişin bir parçasıdır; bunun çoğu otomatikleştirilebilir.
Dönüşümden sonra, buyOrder kutusunu harcamak için gereken tüm ön koşulları kontrol eden doğru bir betik elde edebiliriz.
/** buyOrder sözleşmesi */
def DEX(buyer: Addrss, seller: Address, TID: Int, ergAmt: Long, tAmt: Long)
{
val cancelCondition: SigmaProp = { buyer } // alıcının imzasını doğrula (ProveDlog)
val swapCondition = OUTPUTS.size > 0 && { // OUTPUTS erişimini güvence altına al
val buyerOut = OUTPUTS(0) // buyerOut@0'dan
buyerOut.tokens.size > TID && { // token erişimini güvence altına al
val tid = buyerOut.tokens(TID)
val regR4 = buyerOut.R4[Coll[Byte]]
regR4.isDefined && { // R4 erişimini güvence altına al
val R4 = regR4.get
tid._2 == tAmt && // tAmt: TID'den
R4 == SELF.id && // R4 == bid.id'den
buyerOut.propositionBytes == buyer.propBytes // script == buyer'dan
}
}
}
cancelCondition || swapCondition
}
sellOrder kutusu için benzer bir betik, aynı çeviri kuralları kullanılarak elde edilebilir. Araçların yardımıyla, sözleşmelerin kodu diyagram spesifikasyonundan mekanik olarak oluşturulabilir.
Sonuçlar
Deklaratif programlama modelleri, Big Data, Akış İşleme, Derin Öğrenme, Veritabanları gibi birçok uygulama alanında zorlayıcı programlamaya karşı savaşı kazanmıştır. Ergo, akıllı sözleşmelerin şu anda popüler olan zorlayıcı modeline daha iyi ve daha güvenli bir alternatif olarak dApp geliştirme için deklaratif modeli öncülük etmektedir.
FlowCard kavramı, ErgoScript sözleşmeleri yazmaktan değerlerin genel akışına (bu nedenle adı) odaklanmayı kaydırır; bu şekilde, ErgoScript her zaman bunlardan oluşturulabilir. Araçlar kurulduğunda, ErgoScript koduna asla bakmanıza gerek kalmayacaktır.
Gelecek çalışmalar için olası adımlar şunlardır:
-
FlowCard Spec için depolama formatı ve ilgili EIP standart dosya formatı (Json/XML/Protobuf). Bu, çeşitli araçların (Diyagram Editörü, Çalışma Zamanı, dApp'ler vb.)
*.flowcarddosyalarını oluşturmasına ve kullanmasına olanak tanıyacaktır. -
*.flowcarddosyalarından diyagramlar oluşturabilen FlowCard Görüntüleyici. -
*.flowcarddosyalarını çalıştırabilen, işlemler oluşturup Ergo ağına gönderebilen FlowCard Çalışma Zamanı. -
Karmaşık diyagramların geliştirilmesini basitleştirebilen FlowCard Tasarım Aracı. Bu, Ergo sözleşmelerinin tasarımını ve doğrulamasını hoş bir deneyim haline getirecek; daha çok çizim yapmak gibi, kodlama yerine. Ayrıca, tüm dApp senaryosunun doğruluğu, araçlar tarafından doğrulanabilir ve kontrol edilebilir.
Referanslar
Share post
13 Ağustos 2025
9 Temmuz 2025
12 Mayıs 2025






