對模冪預編譯合約乘法的澄清
我試圖了解 Vitalik 在以下內容中的確切含義(來自此處):
請注意,不需要為加法和減法添加預編譯,因為 in-EVM 算法足夠高效,並且可以通過此預編譯通過
a * b = ((a + b)**2 - (a - b)**2) / 4
.我的理解是,這是執行乘法的一種更有效的方式,但究竟要傳遞給 modexp 合約以實現乘法呢?是 (a+b) 和 (ab) 的平方嗎?在這種情況下,應該將什麼作為模值傳遞?
但是究竟要傳遞給 modexp 合約以實現乘法呢?是 (a+b) 和 (ab) 的平方嗎?
是的,正是這樣。
要計算
a * b % m
,您呼叫預編譯一次來計算(a+b)^2 % m
,再呼叫一次來計算(a-b)^2 % m
,然後取差值(m
必要時添加以保持一切為正)。這給你4 * a * b % m
。為了最終得到
a * b % m
,我們需要除以 4,取模m
。做到這一點的“正確”方法是找到 4 的乘法倒數m
並乘以它。這有點棘手,只有當 m 為奇數時才可能這樣做(即與 4 互質)。$$ But see note at the end $$例子,證明
4 * 5 % 7 = 6
(4 + 5)^2 % 7 = 4 (4 - 5)^2 % 7 = 1 4 - 1 = 3
所以我們有
(4 * (4 * 5)) % 7 = 3
. 模 7, 2 是 4 的倒數(因為(2 * 4) % 7 = 1
)。因此,乘以 2 最終得到(4 * 5) % 7 = 6
QED。在這種情況下,應該作為模值傳遞什麼。
m
與您傳入計算的相同(a * b) % m
。筆記
要使用上面的普通模方法除以 4,我們需要乘以 4 的倒數,即模數
m
。這會給我們一個遞歸問題:進行乘法運算需要我們可以進行乘法運算。但是,我認為有一個捷徑可以用來除以 4 模數
m
。我們除以 2 模數兩次m
。
- 如果
n
是偶數(並且小於m
),那麼n / 2 % m
就是n / 2
- 即右移一位。- 如果
n
是奇數,n / 2 % m
可以簡單地通過計算(n + m) / 2
非模(加n
和m
並右移一位)來找到。所以,在上面的例子
3 / 4 % 7
中發現如下:(3 + 7) / 2 = 5 (5 + 7) / 2 = 6
這與我們之前通過乘以 4 對 7(即 2)的倒數得到的結果相同。