Solidity

如何在不耗盡 gas(攻擊向量)的情況下實現 PubSub?

  • May 8, 2016

一個簡單的 PubSub 模式涉及一組訂閱者。任何人都可以訂閱。發布功能將為每個訂閱者做一些事情。你能發現攻擊向量嗎…?

contract PubSub
{
   address[] subscribers;

   function PubSub() {
   }

   function Subscribe() {
       subscribers.push(msg.sender);
   }

   function Publish(uint value) {

       // if a malicious user spams Subscribe then
       // this loop will never complete, rendering
       // this function unusable
       for(uint i=0; i<subscribers.length; i++) {
           // do something with subscribers[i]...
       }
   }
}

攻擊者可以Subscribe從多個地址呼叫,直到subscribers數組變得如此之大以至於Publish無法使用,總是會遇到氣體不足的錯誤。

在保留發布訂閱功能的同時,有什麼好的方法可以解決這個問題?我在想某種收費的優先級隊列可能是一個解決方案,但我想先在這裡檢查一下,看看有沒有其他人遇到過這個問題,或者有沒有好的解決方案。謝謝!

我是寫契約的新手,所以如果我說什麼愚蠢的話,請忽略。但是,據我了解,如果您有一個攻擊媒介,人們能夠消滅您的資源,那麼您就沒有正確地為您的資源收費。

每次有人訂閱,都會永遠增加所有後續發布的成本。對?因此,如果您不想將該成本轉嫁給發布者,則訂閱者需要支付它。現在,當可能有無限的後續呼叫時,顯然不可能估計訂閱成本publish。根據這種觀點,似乎限制訂閱者將收到的發布數量是唯一合乎邏輯的答案。

這樣,您的 subscribe 函式將接收一個附加參數 ,uint total_messages以指示訂閱者希望接收多少未來消息。當它通過時,他會自動取消訂閱。然後,您只需找到訂閱成本為total_messages * message_cost,其中message_cost用於執行循環的單個迭代的氣體。或者,訂閱者可以有一個餘額,您可以在每次發佈時從中扣除少量乙太幣以支付成本,當使用者用完乙太幣時取消訂閱。或者您可以改為向出版商收費——但這會使出版變得越來越昂貴。

那有意義嗎?

為避免這種情況,只需在數組太大時將其拆分為多個數組,然後發佈到新塊上的每個數組。

這解決了達到gas限制的問題,但並沒有解決成本上升的問題。要解決這個問題,您有幾個選擇。最簡單的方法就是在系統的所有使用者之間分攤成本——如果使用者沒有支付他們的會費,他們就不會被發布。

引用自:https://ethereum.stackexchange.com/questions/3734