向所有結構成員中的項目添加編號
我有一個結構,我想在所有結構成員中增加一個項目。例如,假設有一個 struct ‘Contract’,新客戶獲得自己的 bytes32 ID,它指向他們自己的結構:
mapping(bytes32 => Contract) public contracts; bytes32[] public idList; struct Contract { uint data; uint vintage; }
我想在某個時候將每個結構
contract
項增加 +1。vintage
一種方法是遍歷 ID 數組,取出他們的合約,然後增加項目。for (uint i = 0; i < idList.length; i++) { Contract storage k = contracts[idList[i]]; k.vintage += 1; }
有沒有辦法有效地呼叫
*.vintage += 1;
所以所有的
contracts
結構都一舉增加了元素的年份?
不,它會很昂貴,而且不會擴展。
遊戲的名稱是節省寫入並避免循環。重要的是,您處理此類問題的方法起初可能看起來違反直覺。
如果數據更新到位,您必須計算出該值是多少。為此,您只需要知道原始數字和可能發生的增量數。
pragma solidity 0.5.8; contract Increment { uint epoch; mapping(bytes32 => Contract) private contracts; // suggest rename bytes32[] public idList; struct Contract { // here too uint data; uint vintage; } function newContract(bytes32 id, uint data, uint vintage) public { idList.push(id); // warn: does not check for duplicates Contract storage c = contracts[id]; c.data = data; c.vintage = vintage; } function setEpoch(uint e) public { epoch = e; } function getContract(uint row) public view returns(bytes32 id, uint data, uint age) { require(row <= idList.length); id = idList[row]; Contract storage c = contracts[id]; data = c.data; age = epoch - c.vintage; // <== the magic Incrementer } }
(
contracts
建議重命名)被標記private
為不鼓勵直接使用。相反,依靠getContract()
函式返回您正在尋找的*計算結果。*我使用了一個簡單的設置器,epoch
但它可以逐步發展。進化狀態可能比這個簡單的例子更複雜。例如,可能有必要迭代一些最近的事務來計算目前狀態。例如,考慮一個使用者餘額,即儲存餘額加上自上次更新儲存餘額以來收到的股息。這也帶來了規模化挑戰,因為最終會有太多的紅利來以合理的成本即時處理它。
解決該問題的方法是在有人願意支付汽油費時攤銷工作並進行家務管理。
假設您有一個動態計算餘額的函式:
function computeBalance(address account) public returns(uint balance) { // get stored Balance // add unprocessed dividends // update stored balance <== here's where we sneak in a SSTORE // move the cursor/mark dividends processed <== and here // return balance; }
當它在
view
事務的上下文中執行時,它不會更新狀態,因為它不能。它將返回正確的價值,契約將繼續進行。當它在狀態變化的交易的背景下執行時(不管誰為 gas 付費),它會迅速處理即時的內務管理。強調一下,誰為汽油買單或為什麼買單並不重要。可能是帳戶所有者匯款。可能是有人向帳戶所有者匯款。重要的是有人在做某事 a) 需要平衡 b) 花費 gas。
contractBalance()
在需要最新計算餘額的任何地方,您都可以在整個契約中使用。合約將抓住任何機會對個人賬戶進行一些維護(絕不是整個工程,因為這不會擴展)。在極少數情況下,非活動帳戶可能會積壓太多工作,以至於無法再使用更高階的功能。這是需要小心的事情。
computeBalance()
是public
,因此任何願意支付 gas 費用的人都可以以盡可能低的成本推動它前進(沒有其他問題)。觀察(鏈下)休眠賬戶並確定響應策略(作為公共服務付費?鼓勵所有者付費?取消訂閱?其他?)可能會很方便。這個想法是不惜一切代價避免迭代一個大表。https://blog.b9lab.com/getting-loopy-with-solidity-1d51794622ad
希望能幫助到你。