Cardano’da Akıllı Sözleşmeleri Test Etme

Geçerli bir akıllı sözleşme yazmak hem yetenek hem de titizlik gerektirir. Geliştiriciler tüm olası kullanımları ve senaryoları hesaba katmalıdır.

Tanıtım

Geçerli bir akıllı sözleşme yazmak hem yetenek hem de titizlik gerektirir. Geliştiriciler tüm olası kullanımları ve senaryoları hesaba katmalıdır. Gereksinimler değişirse, varsayımların ve davranışın yeniden doğrulanması gerekebilir. Bu nedenle, gerçek dünyadaki sistemlerde otomatik rastgele testler, akıllı sözleşmelerin doğruluğunu sağlamanın en iyi yoludur.

Geliştirici, testleri tam bir doğruluk kanıtından daha erken uygulayabilir ve rastgele testler bu kanıt için daha az varsayımda bulunur. Bu, özellikle spesifikasyona göre doğruluğu kanıtlanmış akıllı sözleşmeler ışığında, yalnızca spesifikasyonun kusurlarını sonradan ortaya çıkarması açısından önemlidir. Son olarak, iyi yazılmış rastgele testler, doğruluğun kanıtı için makul bir temeldir.

Plutus platformu, popüler bir mülk testi çerçevesi QuickCheck'e dayalı olarak otomatik test için yerleşik desteğe sahiptir.

Bu yazıda, referans örneği olarak “kanıt kanıtı” için akıllı sözleşmemizi kullanarak Plutus akıllı sözleşmesi için otomatik bir testin nasıl yapıldığını gösteriyoruz.

Kripto para birimlerinin ve kripto jetonlarının yakılması, onları bir kara delik adresine gönderiyor: para almak için erişim anahtarı olmayan adres. İşlem gerçekleştikten sonra, halk bir yanmanın gerçekleştiğini doğrulayabilir. Bunu yapmak için gönderenin bir "sır"ı paylaşması gerekir: taahhüt değeri. Proof-of-burn (Karantias, Kiayias ve Zindros 2020), fonların aracılar tarafından sansürlenmeyecek şekilde yakılmasını sağlamak için önerilen bir protokoldür. Blockchain fonlarının yakılması, jetonları geri almaya ve kalan biletlerin değerlemelerini artırmaya hizmet edebilir. Veya blockchain protokollerinde taahhüt kanıtı olarak kullanılabilir (Ismail ve Materwala 2019). Büyük miktarlarda yanma, dolaşımdaki tokenin toplam miktarını azalttığı için deflasyonist baskıya neden olabilir.

*ADA belirteçlerinin yakılması, Cardano'da tanıtımını yaptığımız veya olacağını düşündüğümüz bir şey değildir. Bu yalnızca akıllı sözleşmeleri keşfetmek ve test yöntemlerini açıklamak için kullanılır.

Plutus platformu hem sabit senaryolu standart birim testleri hem de sadece kesin çıktıları değil, özellikleri (“dinamik mantık testleri” olarak da adlandırılır) veya programa uygulanan yasaları test etmeyi amaçladıkları için “özellik testleri” olarak adlandırılan rastgele testleri destekler. Bu tür testler, kullanıcı tarafından belirlenen ve rastgele oluşturulmuş senaryoları birleştirir. Bu, sabit testlere kıyasla çok daha fazla senaryoyu kapsamaya ve hataları daha erken tespit etmeye olanak tanır.

Birim Testi

İlk olarak, Plutus platformu, EmulatorTrace monad kullanılarak akıllı sözleşme birimi testini destekler. Bu monad, test ortamında akıllı sözleşmelerin çağrılmasına izin verir. Bu monad ayrıca cüzdanları simüle eder ve bakiye değişikliklerini izler. Örneğin, akıllı bir sözleşme bir cüzdandan diğerine para gönderirse, EmulatorTrace her iki cüzdanı da simüle eder, para hareketini yakalar ve geliştiricilerin bu cüzdanlardaki son bakiyeleri kontrol etmesine olanak tanır.

Bir kod örneğine bakalım:

Bu test senaryosunda, simüle edilmiş w1 cüzdanından 50 ADA'yı başka bir cüzdan w2 lehine kilitliyoruz ve diğer (örneğin, w3) cüzdanların değişmediğini kontrol ediyoruz.

Burada 3-5 satırlarında testten sonra durum doğrulaması ve 8-13 satırlarında test senaryosunun kendisine sahibiz. Tüm bunlar checkPredicate işlevi tarafından yürütülür. Kullanıcıya görüntülenen testin adını alır, kontrol sonrası ve test senaryosunun kendisini belirtir).

Test senaryosunda, ilk önce, simüle edilmiş cüzdan w1'e (satır 8) bağlı olan proof-of-burn akıllı sözleşmemizin bir hndl1 örneğini yaparız, ardından 10. satırdaki kilit uç noktasını çağırırız. Bu uç noktayı iki argümanla çağırırız: adres nerede toAddr değeri adaValueOf 50'ye gönder. Ardından blok zinciri ortamındaki değişiklikleri test etmek gerekiyor, bu yüzden 11. satırda bir onay işareti bekliyoruz. Ardından simüle edilmiş cüzdan w2'ye (satır 12) bağlı başka bir akıllı sözleşme örneği yapıyoruz ve uç nokta kullanımını çağırıyoruz. Test senaryosu tamamlandı.

Ardından 3-5 satırlarındaki yüklem kontrol edilir. Burada simüle edilmiş cüzdan w1 bakiyesinin 50 ADA azaldığından, w2 bakiyesinin 50 ADA arttığından ve w3 bakiyesinin aynı kaldığından emin oluyoruz.

UnitTests.hs'de proof-of-burn akıllı sözleşmemiz için birim testleri sağladık.

Mülkiyet Testi

Birim testi senaryoları kabloludur (davranışlarını asla değiştirmeyin). Ancak bazen, çok çeşitli davranışlarda akıllı sözleşme özelliklerini kontrol etmek gerekir. Plutus platformu, özellik tabanlı testlere (veya dinamik mantık testlerine) sahiptir. Bu özellik, birden fazla karmaşık test senaryosunun rastgele oluşturularak test edilmesini sağlar.

Bu amaçla, QuickCheck(quickcheck?), bir işleve rastgele girdilerin rastgele oluşturulmasını destekler. Geliştirici, rastgele bir test senaryosu oluşturmak için rastgele oluşturucuyu kullanabilir ve ardından bu senaryonun beklendiği gibi çalışıp çalışmadığını kontrol edebilir.

İlk olarak, geliştiricilerin akıllı sözleşmeyle etkileşim için temel eylemleri belirlemesi gerekir:

Proof-of-burn akıllı sözleşmesinin dört uç noktası vardır, bu nedenle her uç nokta için bir eylem olmak üzere dört eylem sunuyoruz. İlgili eylemde her uç nokta için argümanlar belirtiriz, örneğin, kilit uç noktası için, çekilecek cüzdanı, kullanıldıktan sonra fonların gönderileceği cüzdanı ve değeri belirtiriz.

Artık Plutus platformu gibi rastgele diziler (belirtilen özelliklere sahip) üretebilir. Ortak QuickTest işlevleri kullanılarak ContractModel örneğinde arbitraryAction işlevinde belirtilir:

Mevcut model durumunun bu fonksiyona iletildiğini unutmayın, böylece bu mevcut duruma bağlı olarak eylemler üretebiliriz. Bu, daha karmaşık test senaryolarında kullanılabilir. Örneğin, bazı akıllı sözleşmelerde önce başlatmanın yapılması gerekiyorsa, geçirilen modelState'i kontrol edebilir ve başlatma eylemi oluşturabiliriz. Ardından, başlatma gerçekleştiğinde, diğer tüm eylemleri oluşturabiliriz.

Oluşturulan her dizi iki işlemde çalışır: birincisi simülasyon, ikincisi akıllı sözleşme çalıştırıyor (EmulatorTrace monad'da emülatör altında). Örneğin, Kilitleme eyleminin simüle edilmiş çalışması:

Burada, simüle edilmiş cüzdan wFrom'dan çekilen v değerini işaretliyoruz ve wTo cüzdanı lehine kilitli olanı işaretliyoruz.

Aynı zamanda, test cihazı bu Kilitleme eylemi için akıllı sözleşmeyi de çalıştırır:

Her çalıştırmadan sonra platform, simülasyon sonuçlarının gerçek çalıştırmadaki sonuçlarla eşleşip eşleşmediğini kontrol eder. Özellikle, simüle edilmiş ve gerçek bakiyelerin eşleştiğini kontrol eder. Örneğimizde, EmulatorTrace monad'da callEndpoint @"lock" çalıştırıldıktan sonraki bakiye ile para çekme işleminden sonra simüle edilen bakiyenin eşleştiğini kontrol eder.

Daha önce açıklanan tüm Plutus platform test yetenekleri, belirli ve rastgele eylem dizilerini serbestçe karıştırmaya izin veren dinamik mantık test senaryolarında birleştirildi. Örneğin:

Burada birkaç rastgele eylem gerçekleştiriyoruz ve ardından bazı kilitlerden sonra birkaç Ada'nın kullanılacağını kontrol ediyoruz.

DL test komut dosyasının çalışmasının önemli bir özelliği, hatalı eylem dizilerinin çıktısıdır. Örneğin, yanma kanıtı sözleşmemizi test etmenin erken aşamasında, hatalı bir dizi keşfettik (daha sonra düzelttik, ancak test listemizde bıraktık):

Burada DLScript , Plutus platform koşucusunun (biraz düzeltilmiş) çıktısıdır.

Proof-Of-Burn Akıllı Sözleşmesi İçin Doğrulama Kriterleri

Aşağıda listelenen ilgili mülk testi tarafından sunulan bazı kriterler geliştiriyoruz:

prop_LockAndRedeem – burada, kullanmanın tüm araçları bir kilitle kilitlediğini ve yanmanın buna müdahale etmediğini kontrol ediyoruz. Bunu yapmak için önce kilidi çağırırız, ardından bazı keyfi eylemler, sonra kullan ve sonra kullanılan beklenen değeri kontrol ederiz.

prop_BurnAndVerify – öncekine benzer, ancak kilitlemenin/kullanmanın yanma/validateBurn ile etkileşime girmediğini kontrol ederiz.

prop_RandomActionsIsConsistent – ​​saf rastgele eylemler. Test modelimizin dahili iddiaları vardır ve herhangi bir eylem dizisi için tüm bu iddiaları doğrulamalıdır.

Daha önce belirtildiği gibi, dinamik mantık test çalıştırıcısı, bazı hataların meydana geldiği DLTest eylem listesinin çıktısını alabilir. Proof-of-burn'umuzu geliştirirken bu tür sorunlarla karşılaştık ve bu çıktıyı testlere kaydettik. Yani elimizde iki tane var:

prop_BurnValidatingInEmulatorIsWorks – ValidateBurn'ın test modellerinde doğru çalıştığını kontrol eder.

prop_GetObservableStateDon'tBreakEmulator - Görünüşe göre Plutus öykünücüsünde bir hatayla karşılaştık ve burada test modelimizin bunu atladığını kontrol ediyoruz.

Çözüm

Hızlı bir tasarım kontrolü olarak, geliştirici ortak birim testlerini kullanabilir. Ancak özellik tabanlı testler, rastgele test senaryoları oluşturarak çok daha kapsamlı testlere izin verir. Bir ControlMonad örneği (ve bazı yardımcı kodlar) yazmak gerekir, ancak daha sonra geliştiriciler akıllı sözleşmeleri birçok kez daha fazla test senaryosuna karşı doğrulayabilir ve akıllı sözleşmede çoğu hatayı bulabilir.

Plutus platformunun kapsamlı test yeteneklerini kullanarak uygulamamızın performansını kontrol ettik ve birçok hatayı düzelttik.