數學魔法 (以太坊中的)乘法部分

2021-09-20 06:06:04 字數 1904 閱讀 3599

翻譯 | 餘杭      校對 | 醬番梨      審核 | 醬番梨

大量的智慧型合約使用 safemath 庫,以確保合約的結果正確,但它是通過使交易失敗,而不是矯正它們。讓我們嘗試進行正確的數**算。在本系列中,我會對一些先進的技術進行推導。今天,我會改良 safemul 庫。

如果對兩個數值進行相乘,結果會是之前的兩倍大小。在以太坊中,對兩個數值進行相乘,結果最高會是 512 位。但以太坊僅僅給出結果的下半部分,它會忽略剩餘部分。這在數學中稱作模數運算。

然而,省略數字在會計中是不可接受的。因此必須想辦法避免這種情況的發生,不然會導致某些人失去非常有價值的東西。乙個非常受歡迎的庫叫做 safemath 。

當這種情況發生時 safemath 就會檢測到然後終止交易,但如果你不希望交易終止又該如何呢?

如果你想要對任意數值進行想成並且想要得到乙個完整的結果又該怎麼辦呢?

在我們深入了解之前,先正確定義問題:即已知兩個無符號數值 a 和 b ,並且它們的長度都是 256 位,並且希望得到它們的乘積,即 512 位數字 x 。 

教科書演算法

解決這個問題的經典方法是長乘,這個方法我們在學校已經學習過了。把大數拆分成較小的數,乘以對應位的數值,然後把結果相加。這個方法同樣適用於二進位制和其他進製。讓我快速地向你們展示在這裡如何使用它.

因為支援 256 位內建乘法,所以我們可以對任意兩個 128 位數相乘然後得到全部的結果。因此如果把大數拆分成每組 128 位,那麼我們可以計算出所有的結果。取 a0 和 a1 分別對應於 a 的最低有效 128 位和最高有效 128 位,對 b 也是類似的操作:

我會跳過如何從這個表示式中獲取 r0 和 r1 的部分,因為它雖然直接,但是轉換和代入過程非常惱人。最終的結果是: 

(請注意如果 solidity 編譯器的版本為 0.4.18,那麼在編譯上述例項時會失敗,因為編譯器無法處理過多的本地變數。但這可以通過內聯表示式很輕鬆地解決,但因為這會降低可讀性所以我沒有選擇在本例中使用內聯表示式。)

i01 以及 i10 兩個乘式可以通過 karatsuba 演算法合併成乙個乘式,這是在消耗額外的 gas 為代價的前提下。因為額外的 gas 量為 3,而整個乘式消耗的 gas 量為 5,因此並不值得使用 karatsuba 演算法。但是如果想要做更大位數的乘法(比如 4096 位),那麼值得使用 karastuba 演算法。

通過使用兩個取模運算,四個除法,六個加法,兩個條件分支,以及不少於六個乘法,我們已經解決了這個問題。整個函式總消耗超過 300 gas。這似乎還不錯,但是 gas 的消耗量已經超過正常乘法 5 gas 消耗的 2 個數量級,或是標準 safemul 的 90 倍。我們可以做得更好。

中國的餘數定理

技巧部分:使用 mulmod 指令以及中國的餘數定理,簡而言之,定理闡述的是如果已知乙個數的模是 2 的 256 次方 以及 2 的 256 次方 -1,那麼我們可以計算出它的 512 位表示方法,使用的函式是 chineseremainder , 在 a previous post 中有過相關描述。我們首先需要計算出兩個取模運算的結果:

不同領域包括計算機視覺,語音語義,區塊鏈,自動駕駛,資料探勘,智慧型控制,程式語言等每日更新。

以太坊中的賬戶 Account

1.什麼是賬戶?乙太坊是乙個p2p網路,任何人只要有一台可以聯網的電腦,都可以參與到這個網路中。普通使用者參與到乙太坊網路中,最常見的目的,就是進行乙太幣交易。比方說a要把100個eth轉給b,這就會生成一比交易。這筆交易會被打包到乙個區塊中,由礦工將其加入區塊鏈中。礦工做這件事的過程就是記賬,或者...

以太坊中的安全代幣案例

鏈客 有問必答!我在關於安全令代幣 第一部分,第二部分 有爭議的文章中,我提到過,以太坊可能不是長期執行安全代幣的平台,這是很有可能的。這個想法可能看起來很可笑,因為以太坊幾乎是加密貨幣 生態系統中唯一活躍的平台。然而,一旦您在安全代幣的未來架構中平衡了以太坊的限制,那麼推理就開始有意義了。我是以太...

19 以太坊中的挖礦演算法

對於基於區塊鏈證明的區塊鏈系統來說,挖礦是保障區塊鏈安全的重要手段,block chain is secured by mining。bug bounty 在美國電影裡面有賞金獵人 bounty hunter 這個是說懸賞去找挖礦bug。在位元幣的挖礦演算法是是安全的,但是在位元幣系統中存在必須使用...