Akıllı sözleşmelerin yeniden yapılandırılması: işlev seçici nedir?

Merhaba, akıllı sözleşmeleri yeniden yapılandırmaya devam etmeme hoş geldiniz. Bu makale bir dizi makalenin üçüncü bölümüdür. Önceki makaleleri okumadıysanız, lütfen bir göz atın:

Basit bir Solidity akıllı sözleşmesinin EVM bayt kodunu çözüyoruz.

Bir önceki makalede, akıllı sözleşmenin bayt kodunun iki kısma ayrıldığını belirledik: oluşturma ve çalıştırma ve bunu neden yaptığımızı biliyorduk.Yaratım kısmını anladıktan sonra, çalışma zamanı kısmını keşfetmeye başlamanın zamanı geldi. Yukarı. Yapısızlaştırma diyagramına bakarsanız, önce BasicToken.evm (runtime) adlı ikinci büyük bölünmüş bloğa bakabiliriz.

Bu biraz korkutucu görünebilir, çünkü çalışan kodun uzunluğu oluşturulan kodun boyutunun en az dört katıdır! Ancak endişelenmeyin, EVM kodunu anlamak için önceki makalede geliştirdiğimiz beceriler, kesinlikle güvenilir bir "böl ve yönet" stratejisi kullanımımızla birleştiğinde, bu zorluğu daha sistematik ve muhtemelen daha da kolaylaştıracak. Bu sadece başlangıç, bağımsız yapıları belirlemeye ve çözülebilir problemlere bölünene kadar onları ayırmaya devam edeceğiz.

İlk olarak, Remix çevrimiçi düzenleyicisine geri dönelim ve bir hata ayıklama oturumu başlatmak için çalışma zamanı bayt kodunu kullanalım. Biz ne yaptık? Geçen sefer akıllı sözleşmeyi uyguladık ve dağıtım işleminin hatalarını ayıkladık. Bu sefer, konuşlandırılmış akıllı sözleşme arayüzü ile etkileşim kurmak ve işlemde hata ayıklamak için işlevlerden birini kullanacağız.

İlk olarak, akıllı sözleşmemizi birlikte hatırlayalım:

Optimize edilmiş derleyici Javascript VM, sürüm v0.4.24'ü etkinleştirdik ve başlangıç kaynağı olarak 10000'i ayarladık. Akıllı sözleşmeyi dağıttıktan sonra, Remix'teki "çalıştır" panelinin "Dağıtılmış Sözleşmeler" bölümünde listelendiğini görmelisiniz. Akıllı sözleşmenin arayüzünü görmek için genişletmek için tıklayın.

Bu arayüz nedir? Akıllı bir sözleşmedeki tüm genel veya harici yöntemlerin bir listesidir - yani herhangi bir Ethereum hesabı veya akıllı sözleşme onunla etkileşime girebilir. Özel ve dahili yöntemler burada gösterilmeyecektir.Akıllı sözleşme çalışma zamanı kodunun belirli bölümleriyle nasıl etkileşim kurulacağı bu makalenin yapısökümünün odak noktası olacaktır.

Remix'in "çalıştır" panelindeki totalSupply düğmesine tıklayarak deneyebiliriz. Düğmenin altındaki yanıtı hemen görmelisiniz, bu beklediğimiz şeydir çünkü akıllı sözleşmeyi ilk belirteç kaynağı olarak dağıtıyoruz. Şimdi, Konsol panelinde, bu belirli işlemle bir hata ayıklama oturumu başlatmak için Hata Ayıkla düğmesine tıklayın. Lütfen Konsol panelinde birden fazla Hata Ayıklama düğmesi olacağını unutmayın; en son sürümü kullandığınızdan emin olun.

Bu durumda, bir önceki makalede gördüğümüz gibi 0x0 adresindeki işlemde hata ayıklamadık, akıllı bir sözleşme oluşturduk. Bunun yerine, akıllı sözleşmenin kendisine, yani çalışma zamanı koduna yönelik işlemin hatalarını ayıklıyoruz.

"Talimatlar" paneli açılırsa, Remix'te listelenen talimatların, dönüştürülmüş görüntünün BasicToken.evm (çalışma zamanı) bölümündekilerle aynı olduğunu doğrulayabilmelisiniz. Eşleşmiyorlarsa bir sorun var. Baştan başlamayı deneyin ve yukarıdaki doğru ayarları kullandığınızdan emin olun.

Fark edebileceğiniz ilk şey, hata ayıklayıcının sizi talimat 246'ya koyması ve işlem kaydırıcısının bayt kodunun yaklaşık% 60'ı olmasıdır. neden? Remix çok cömert bir program olduğundan, sizi doğrudan EVM'nin totalSupply işlevinin gövdesini yürütecek kısmına götürür. Ancak bundan önce çok şey oldu ve burada dikkat etmemiz gerekenler bunlar. Aslında, bu makalede işlev gövdesinin yürütülmesini incelemeyeceğiz bile. . Tek endişemiz, Solidity tarafından üretilen EVM kodunun gelen işlemleri nasıl yönlendirdiğidir, bu da sözleşmenin "işlev seçici" olarak anlayacağımız şeydir.

Öyleyse, kaydırıcıyı tutun ve tamamen sola sürükleyin, böylece sıfır talimatından başlayalım. Daha önce gördüğümüz gibi, EVM her zaman istisnasız komut 0'dan kod çalıştırır ve sonra kodun geri kalanında akar. Bu yürütme işlem kodunu opcode ile tamamlayalım.

Ortaya çıkan ilk yapı daha önce gördüklerimizdir (aslında çok şey göreceğiz):

Şekil 1. Boş bellek işaretçisi

Bu, Solidity tarafından oluşturulan EVM kodunun aramadan önce her zaman gerçekleştireceği herhangi bir şeydir: daha sonra kullanmak için belleğe bir nokta kaydedin.

Bakalım sonra ne olacak:

Şekil 2. Veri uzunluğu kontrolü arayın.

Remix'in Yığın panelini Hata Ayıklama sekmesinde açarsanız ve 5'ten 7'ye kadar olan talimatları atlarsanız, yığının artık iki sayı içerdiğini göreceksiniz. Bu ekstra uzun sayıları okumakta sorun yaşıyorsanız, lütfen Remix hata ayıklama panelinin genişliğini, sayıların tek bir satıra tam olarak sığması için ayarlamaya dikkat edin. İlki normal itmeden gelir, ancak ikincisi işlem kodunun yürütülmesinin sonucudur. Sarı Kitap'ta açıklandığı gibi, parametresi yoktur ve "mevcut ortamdaki giriş verilerinin" boyutunu döndürür veya biz buna genellikle calldata deriz: 4CALLDATASIZE

Çağrı verileri nedir? Solidity'nin ABI spesifikasyonunda açıklandığı gibi, çağrı verisi, çağırmak istediğimiz akıllı kontrat işlevi ve ayrıca parametreleri veya verileri hakkında bilgi içeren onaltılık sayılardan oluşan bir kodlama bloğudur. Basitçe ifade etmek gerekirse, hash fonksiyon imzası (ilk dört bayta kesilir) ve daha sonra sıkıştırılmış parametre verileriyle oluşturulan bir "fonksiyon kimliği" içerir. Gerekirse, belge bağlantılarını ayrıntılı olarak inceleyebilirsiniz, ancak bu paketin en ince ayrıntısına kadar nasıl çalıştığı konusunda endişelenmeyin. Dokümantasyonda açıklanmıştır, ancak bir seferde ustalaşmak biraz zordur. Pratik örneklerle anlamak çok daha kolay olacak.

Bakalım bu arama verisi ne. Remix hata ayıklayıcısında "Verileri Geri Çağır" panelini açın ve şu görünümü görüntüleyin: 0x18160ddd. Bu, algoritmanın keccak256 işlev imzası üzerinde bir dizge olarak uygulanması ve kesmenin gerçekleştirilmesi ile doğru bir şekilde oluşturulan dört baytlık "toplamSupply" dir. Bu belirli işlev parametre almadığından, sadece: dört baytlık bir işlev kimliği. CALLDATASIZE çağrıldığında, ikincisini yığına iter.

Ardından, çağrı verilerinin boyutunun 4'ten küçük olup olmadığını doğrulamak için 8 LT talimatı kullanılır. Eğer öyleyse, aşağıdaki iki komut JUMPI komutunu 86 (0x0056) yürütür. Bu dört bayttan azdır, bu durumda herhangi bir atlama olmayacak ve yürütme akışı komut 13'ü yürütmeye devam edecek. Ancak bunu yapmadan önce, akıllı sözleşmemizi boş çağrı verileri ile çağırdığımızı varsayalım. Yani, 0x18160ddd yerine 0x0. Bunu Remix btw ile yapamazsınız, ancak işlemleri manuel olarak oluşturabilirsiniz.

Bu durumda, temelde yığına birkaç sıfırı iten ve bunları REVERT işlem koduna sağlayan 86 numaralı talimatla son buluruz. neden? Eh, çünkü bu akıllı sözleşmenin yedekleme işlevi yok. Bayt kodu gelen veriyi tanımazsa, akışı geri dönüş işlevine aktaracaktır.Yapı çağrıyı "yakalayamazsa", kurtarma yapısı yürütmeyi sonlandıracak ve kesinlikle geri dönüş olmayacaktır. Geri dönecek bir şey yoksa, yapacak bir şey yoktur ve çağrı tamamen geri yüklenir.

Şimdi daha ilginç bir şey yapalım. Remix'in Çalıştır sekmesine geri dönün, Hesap adresini kopyalayın ve işlemde hata ayıklamak için totalSupply yerine balanceOf'u çağırmak için bir parametre olarak kullanın. Bu yepyeni bir hata ayıklama oturumu; şimdilik totalSupply'ı unutalım. 8. talimata gidin, CALLDATASIZE artık 36'yı (0x24) yığına iter. Calldata'ya bakarsanız, şimdi 0x70a08231000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c olur.

Bu yeni çağrı verilerinin ayrıştırılması aslında çok kolaydır: ilk dört bayt 70a08231 imzanın karmasıdır ve "balanceOf (adres)" in arkasındaki 32 bayt parametre olarak geçirdiğimiz adresi içerir. Ethereum adresi sadece 20 bayt uzunluğundaysa neden 32 bayt, meraklı okuyucular sorabilir? ABI, işlev çağrılarında kullanılan parametreleri saklamak için her zaman 32 baytlık "sözcükler" veya "yuvalar" kullanır.

Bakiyemizde devam ediyor Çağrı ortamımız, yığında hiçbir şey yokken, 13. talimatta bıraktığımız yerden ayrılalım. Komut 13 daha sonra 0xffffffff'ı yığına iter ve sonraki komut 29 bayt uzunluğundaki 0x000000001000 ... 000 numarasını yığına iter. Nedenini yakında anlayacağız. Şimdi, birinin dört bayt ve diğerinin dört bayt 0 'içerdiğine dikkat edin.

Sonra, CALLDATALOAD bir parametre alır (komut 48'de yığına itilen) ve bu pozisyondaki çağrı verilerinden 32 baytlık bir blok okur. Bu durumda, Yul'da olacaktır:

calldataload (0)

Temel olarak tüm çağrı verilerimi yığına gönder. Şimdi ilginç kısım geliyor. DIV yığından iki parametre kullanır, çağrı verilerini alır ve onu garip 0x000000001000 ... 000 numarasına böler, çağrı verilerindeki işlev imzası dışındaki her şeyi etkin bir şekilde filtreler ve onu yığında bırakır: 0x000 ... 000070a08231. Bir sonraki talimat, aynı zamanda yığındaki iki öğeyi de tüketen AND'yi kullanır: işlev kimliğimiz ve dört baytlık f sayısı. Bu, imza özetinin tam olarak sekiz bayt uzunluğunda olmasını sağlamak içindir ve başka herhangi bir içerik varsa, diğer içerikler engellenir. Solidity'nin kullandığı güvenlik önlemlerinin olduğunu düşünüyorum.

Kısacası, çağrı verilerinin çok kısa olup olmadığını kontrol ediyoruz, öyleyse, onu geri yüklüyoruz ve daha sonra, yığında işlevimizi elde etmek için biraz iyileştiriyoruz,

Ayrıca neredeyse bitirdik. Sonraki bölümün anlaşılması kolay olacak:

Şekil 3. İşlev seçici

53 talimatında, kod 18160ddd'yi (toplam işlev kimliği totalSuppy) yığına iter ve ardından yığın üzerinde halihazırda ikinci konumda bulunan 70a08231 gelen çağrı verisi değerini kopyalamak için bir DUP2 kullanır. Neden kopyalayasınız? EQ talimatı 59'daki işlem kodu yığında iki değer tüketeceğinden ve 70a08231 değerini korumak istiyoruz çünkü onu çağrı verilerinden çıkarma sıkıntısı yaşadık.

Kod şimdi çağrı verilerindeki işlev kimliğini bilinen işlev kimliklerinden biriyle eşleştirmeye çalışacaktır. 70a08231 girildiğinden beri, 18160ddd ile eşleşmeyecek ve JUMPIAt komutu 63'ü atlayacaktır. Ancak bir sonraki kontrolde eşleşecek ve 74 numaralı talimatta JUMPI'ye geçecektir.

Akıllı sözleşmenin her bir kamu veya dış işlevi için bu eşitlik kontrollerini gözlemlemek için bir dakikanızı ayıralım. Bu, işlev seçicinin özüdür: bir tür anahtar ifadesi olarak hareket eder, basitçe yürütmeyi kodun doğru bölümüne yönlendirir. Bu bizim "merkezimiz" dir.

Bu nedenle, son durum bir eşleşme olduğundan, yürütme akışı bizi JUMPDESTat pozisyonu 130'a götürür, bu serinin bir sonraki bölümünde, balanceOf fonksiyonunun ABI "sarmalayıcısı" nı göreceğiz. Göreceğimiz gibi, bu paketleyici, işlem verilerini işlev gövdesi tarafından tüketilmek üzere açmaktan sorumlu olacaktır.

Bu sefer transfer hata ayıklama işlevini denemeye devam edin. İşlev seçici gerçekten gizemli değil. Bu, her sözleşmenin kapısında oturan (en azından Solidity'den derlenenlerin tümü) ve yürütmeyi kodda uygun yere yönlendiren basit ve etkili bir yapıdır. Bu, Solidity'nin akıllı sözleşmelerin bayt kodu için birden çok giriş noktasını ve dolayısıyla arayüzü simüle etme becerisini sağlamasıdır.

Yapıbozum diyagramına bir bakın, az önce yapısökümünü yaptığımız şey bu:

Şekil 4. İşlev seçici ve akıllı sözleşmenin çalışma zamanı kodunun ana giriş noktası.

Sonuçta beyler, farkında olmadan Solidity'nin temelindeki kodu çoğu insandan daha iyi biliyorsunuz, ona bağlı kalın ve onu tamamen açabilirsiniz.

* Bu makale ilk olarak Alejandro Santander tarafından medyada yayınlandı ve Cheetah Blockchain tarafından güvenli bir şekilde tercüme edildi ve derlendi *

En yüksek rakıma sahip ülkeye girmek için bu araba en iyi seçim olabilir!
önceki
CCTD Beklenen iyileşme, kömür fiyatlarındaki düşüş yavaşlıyor
Sonraki
Bu araba Çin'de yapılmak üzere ve Amerikan otomobil satıcıları büyük baskı altında.
Babbitt ilk
100.000 ABD Doları Chuanghuayi BAT için çalışıyor, Bona ayrıca devlerin A paylaşımına dönmesine güveniyor ve büyük adamlar film yapmayı seviyor
CCTD Ulusal Enerji İdaresi, Ocak'tan Ekim'e kadar ulusal enerji sektörü istatistiklerini yayınladı
Doğu tarafı parlak değil, batı tarafı parlak, Fiat kahramanı Jeep'e yol veriyor
CCTD Günlük Kömür Piyasası Bilgileri Kısa Bilgi (11.26)
Fiyat 49,900-73,9 milyon yuan, yeni Rena baskı olmadan çeşitli lehçelerin kilidini açıyor
Mobike ofo fon sıkıntısı çekiyor ve 6 milyar kullanıcı mevduatını zimmete mi geçirdi? ! Her iki taraf da cevap verdi
Oynaması eğlenceli, LITE'ın ön satışı 86.800 yuan'dan başlıyor ve 10'a kadar avantaj
CCTD Çeşitli bölgelerden seçilmiş kömür fiyatları (11,26)
Küçük bir makaralı iğne, aslında tüm otomobil pazarının üretimini 3 milyon azaltacak mı?
Babbitt sütunu
To Top