如何在不耗盡 gas(攻擊向量)的情況下實現 PubSub?
一個簡單的 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限制的問題,但並沒有解決成本上升的問題。要解決這個問題,您有幾個選擇。最簡單的方法就是在系統的所有使用者之間分攤成本——如果使用者沒有支付他們的會費,他們就不會被發布。