什么是預(yù)編譯合約?
預(yù)編譯合約是 EVM 中用于提供更復(fù)雜庫(kù)函數(shù)(通常用于加密、散列等復(fù)雜操作)的一種折衷方法,也可以理解為一種特殊的合約,這些函數(shù)不適合編寫(xiě)操作碼。 它們適用于簡(jiǎn)單但經(jīng)常調(diào)用的合約,或邏輯上固定但計(jì)算量很大的合約。 預(yù)編譯合約是在使用節(jié)點(diǎn)客戶端代碼實(shí)現(xiàn)的,因?yàn)樗鼈儾恍枰?EVM,所以運(yùn)行速度很快。 與使用直接在 EVM 中運(yùn)行的函數(shù)相比,它對(duì)開(kāi)發(fā)人員來(lái)說(shuō)成本也更低。
如下代碼可以看到, evm.go的合約中run函數(shù)有兩個(gè)分支:第一個(gè)分支是通過(guò)預(yù)編譯索引來(lái)實(shí)例化索引參數(shù)從而指定預(yù)編譯合約,第二個(gè)分支是如果它不是預(yù)編譯合約那evm將會(huì)被調(diào)用。
// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
if contract.CodeAddr != nil {
precompiles := PrecompiledContractsHomestead
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
precompiles = PrecompiledContractsByzantium
}
if p := precompiles[*contract.CodeAddr]; p != nil {
return RunPrecompiledContract(p, input, contract)
}
}
for _, interpreter := range evm.interpreters {
if interpreter.CanRun(contract.Code) {
if evm.interpreter != interpreter {
// Ensure that the interpreter pointer is set back
// to its current value upon return.
defer func(i Interpreter) {
evm.interpreter = i
}(evm.interpreter)
evm.interpreter = interpreter
}
return interpreter.Run(contract, input, readOnly)
}
}
return nil, ErrNoCompatibleInterpreter
}
用圖形來(lái)表示的話,具體的邏輯如下圖:
那么預(yù)編譯合約的瓶頸在哪里?
以太坊目前有八個(gè)預(yù)編譯的合約:
- ECRecover - 通過(guò)簽名恢復(fù)對(duì)應(yīng)地址
- SHA256 - 計(jì)算SHA256哈希
- RIPEMD160 - 計(jì)算RIPEMD160哈希
- Identity - 返回輸入數(shù)據(jù)的原值
- ModExp - 進(jìn)行模數(shù)指數(shù)運(yùn)算
- ECAdd - 橢圓曲線點(diǎn)加法
- ECMul - 橢圓曲線點(diǎn)乘法
- ECPairing - 配對(duì)運(yùn)算,驗(yàn)證橢圓曲線點(diǎn)
可以看到第一到第四個(gè)預(yù)編譯合約提供的基礎(chǔ)的簽名,哈希等加密功能,第五個(gè)到第八個(gè)提供了橢圓曲線運(yùn)算,這些和zk-snark相關(guān)。
那么問(wèn)題來(lái)了,為什么以太坊預(yù)編譯只支持了八個(gè)預(yù)編譯合約,預(yù)編譯合約不是降低了gas消耗嗎?而且為什么不直接把ECS(全鏈游戲的框架)植入以太坊預(yù)編譯合約中呢?
其實(shí)主要是以下三個(gè)原因:
1.過(guò)度依賴預(yù)編譯合約會(huì)降低整個(gè)平臺(tái)的去中心化程度:
首先,預(yù)編譯合約的代碼需要集成在客戶端節(jié)點(diǎn)代碼中,增加了客戶端的復(fù)雜性。第二,驗(yàn)證節(jié)點(diǎn)可能因?yàn)榘踩蚩赡軙?huì)過(guò)濾掉預(yù)編譯合約的計(jì)算,所以大部分預(yù)編譯合約的請(qǐng)求是由全節(jié)點(diǎn)完成的,目前全球的以太坊全節(jié)點(diǎn)的數(shù)量只有4000-6000個(gè),而且驗(yàn)證節(jié)點(diǎn)有50萬(wàn)個(gè),確實(shí)比起非預(yù)編譯合約要中心化很多。
2.預(yù)編譯合約的新增和修改需要硬分叉升級(jí),不易靈活演進(jìn)。
預(yù)編譯合約的支持需要進(jìn)行EIP流程,舉個(gè)例子:EIP-196增加了在alt_bn128曲線上的ECADD()和ECMUL()兩個(gè)預(yù)編譯合約。EIP-197增加了在alt_bn128曲線上的配對(duì)Pairing函數(shù)?;径际菫榱俗岆[私在以太坊上可用進(jìn)行支持,而且整個(gè)EIP的流程是漫長(zhǎng)和考究的,等待EIP通過(guò)也不是一個(gè)現(xiàn)實(shí)的問(wèn)題。
3.預(yù)編譯合約之間難以進(jìn)行交互和組合,擴(kuò)展性差。
這點(diǎn)就不多做解釋了,很直觀。
預(yù)編譯合約在全鏈游戲扮演什么角色?
預(yù)編譯合約跳過(guò)EVM直接通過(guò)節(jié)點(diǎn)執(zhí)行,可以提升運(yùn)算效率,但同時(shí)降低了全鏈的去中心化程度。將高頻使用的游戲核心邏輯置于預(yù)編譯中,可以優(yōu)化該類游戲的性能。不同的游戲類型,其關(guān)鍵邏輯也不盡相同。因此,針對(duì)某一類游戲的專用鏈上,其預(yù)編譯設(shè)計(jì)可以高度優(yōu)化該類型游戲的需求。在游戲迭代過(guò)程中,最具效率的預(yù)編譯合約組合也會(huì)逐步優(yōu)化出來(lái)。
免責(zé)聲明:本文不構(gòu)成投資建議,用戶應(yīng)考慮本文中的任何意見(jiàn)、觀點(diǎn)或結(jié)論是否符合其特定狀況,及遵守所在國(guó)家和地區(qū)的相關(guān)法律法規(guī)。
歡迎轉(zhuǎn)載分享!
轉(zhuǎn)載請(qǐng)注明本文地址:
如有文章侵犯了您的權(quán)利,請(qǐng)聯(lián)系本站站長(zhǎng),我們將在第一時(shí)間刪除相關(guān)內(nèi)容,謝謝!