# EIP-3670: 智慧合約的程式碼檢查
# 注意事項
本文並沒有經過作者外的其他審查者審核,因此若內容有誤,請到 issue 區提出問題,我會儘速修改,謝謝。
# 什麼是這個提案?
這個提案是要在以太坊區塊鏈上,當有人想要建立新的智慧合約時,先檢查程式碼是否正確。就像老師在你交作業前先檢查你的作業有沒有寫完整一樣!
# 為什麼需要這個提案?
想像一下,如果你在寫國語作文時,有些字沒寫完整或是用了不存在的字,別人讀的時候就會很困惑。現在的智慧合約就有這個問題 - 它們可能包含「不完整的指令」或「不存在的指令」,讓電腦執行時很困惑。
這個提案要讓所有人同意:只有「寫得完整」且「只用已知操作碼」的位元組碼才能成為智慧合約。這樣大家就能更容易理解程式碼在做什麼,電腦也能更有效率地執行它們。
# 這個提案會怎麼運作?
當有人想要建立新的智慧合約時,系統會檢查程式碼是否符合以下規則:
不能使用已經「被淘汰」的操作碼,就像你不能在現代作文中使用已經廢除的繁體字一樣。
程式碼需要「完整」:
- 每個操作碼必須是電腦認識的(就像你寫的每個字都必須是真實存在的字)
- 程式碼不能寫到一半就斷掉(就像你的句子不能說到一半就...)
# 這個提案有什麼好處?
- 程式設計師可以更確定他們的程式會被正確執行
- 系統可以更有效率地運作
- 未來如果要增加新的操作碼,不會跟已經存在的程式衝突
# 會影響到舊的程式嗎?
不會喔!這個提案只會影響到新的、使用特殊格式(叫做EOF,以太坊物件格式)的智慧合約。舊的程式完全不受影響,可以繼續正常運作。
# 舉個例子
想像你在玩一個積木遊戲:
- 合格的程式:所有積木都是玩具組裡有的積木,而且每個積木都放好了。
- 不合格的程式:有些積木是你自己畫的(系統不認識的操作碼),或是有些積木只放了一半(不完整的指令)。
這個提案就是要確保所有新建立的智慧合約都是「合格的程式」。
# 實際的程式碼範例解釋
以下是一段檢查程式碼是否符合規則的程式碼,我會用簡單的方式解釋:
# 以下是上海版本以太坊可以使用的操作碼
# 備註:range(s, e) 不包含 e,所以要 +1
shanghai_opcodes = [
*range(0x00, 0x0b + 1), # 這些數字代表不同的操作碼
*range(0x10, 0x1d + 1),
0x20,
*range(0x30, 0x3f + 1),
*range(0x40, 0x48 + 1),
*range(0x50, 0x5b + 1),
0x5f,
*range(0x60, 0x6f + 1),
*range(0x70, 0x7f + 1),
*range(0x80, 0x8f + 1),
*range(0x90, 0x9f + 1),
*range(0xa0, 0xa4 + 1),
# 備註:0xfe 是被認可的操作碼
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xfa, 0xfd, 0xfe, 0xff
]
# 剔除在這裡和 EIP-3540 中被淘汰和拒絕的操作碼
rejected_in_eof = [
0x38, 0x39, 0x3b, 0x3c, 0x3f, 0x5a, 0xf1, 0xf2, 0xf4, 0xfa, 0xff
]
valid_opcodes = [op for op in shanghai_opcodes not in rejected_in_eof]
# 這裡定義了每個操作碼需要多少額外資料
immediate_sizes = 256 * [0]
immediate_sizes[0x60:0x7f + 1] = range(1, 32 + 1) # PUSH1..PUSH32 需要 1-32 個額外資料
# 如果程式碼無效,這個函式會發出錯誤訊息
def validate_instructions(code: bytes):
# 注意 EOF1 已經確保這一點
assert len(code) > 0 # 程式碼長度必須大於 0
pos = 0
while pos < len(code):
# 確保操作碼是有效的
opcode = code[pos]
if opcode not in valid_opcodes:
raise ValidationException("未定義的操作碼") # 如果使用了不存在的操作碼,就報錯
# 跳過此操作碼的額外資料
pos += 1 + immediate_sizes[opcode]
# 確保最後一個操作碼的額外資料不會超出程式碼結尾
if pos != len(code):
raise ValidationException("不完整的操作碼") # 如果操作碼被截斷,就回傳錯誤
# 這段程式碼在做什麼?
想像你在校對一篇作文:
- 首先,你有一份「合法字詞表」(
valid_opcodes
) - 你從頭到尾一個字一個字地檢查:
- 如果發現一個不在「合法字詞表」上的字,你就說「這個字不存在!」
- 有些字(像 PUSH 操作碼)需要後面跟著額外的資料,就像有些中文字需要部首和筆畫
- 最後,你還要確保所有的字都完整了,沒有寫到一半就結束
這段程式碼就是在做這樣的檢查,確保智慧合約的位元組碼完全符合規則。
# 有效和無效的程式碼例子
# 有效的程式碼
- 包含
INVALID
(0xfe) 操作碼的 EOF 程式碼(雖然叫「無效」,但它其實是一個有效的操作碼) - 資料區段包含未定義操作碼的 EOF 程式碼(資料區段不執行,所以裡面放什麼都可以)
# 無效的程式碼
- 包含未定義操作碼的 EOF 程式碼(就像用了不存在的字)
- 結尾是不完整
PUSH
操作碼的 EOF 程式碼(就像寫了一個需要部首的字,但沒把部首寫完)
這樣設計可以確保所有新的 EOF 格式智慧合約都是「正確無誤」的,讓以太坊區塊鏈運作更加穩定和安全!