本文參考EOS版本:v1.1.1
一.EOS投票相關
//用戶投票
1.不能自己代理自己,但可以自己給自己投票;
2.投票的生產節點名稱不能重復;
3.投票人設置了投票代理人后自己不能再投票;
4.投票人需要先抵押EOS,才有資格進行投票(多索引列表voters);
5.用戶投票隨時可以撤銷再次進行投票,需要花費一定數量的CPU與NET資源;
6.一個EOS分為30票,一次最多可以投給30個節點;
7.用戶一次投一個節和投多個節點,對於每個節點得到的票數是一樣的。
例如用戶抵押100EOS給節點a投票,節點a得到3000票;如果用戶抵押100EOS給節點a,b同時投票,則節點a,b分別都得到3000票
//注冊節點
1.所有已注冊成的節點只有在運行時(active狀態)才能獲得用戶的選票,否則用戶給此節點投票是無效的;
2. 所有已注冊成的節點的獲得的選票是實時統計的,如果有一個超過21個主節點,將會成為超級節點進行出塊;
3.用戶user1,user2,user1抵押100個EOS,user2抵押1000個EOS,進行投票給一個節點,則user2的投票數量是user1的10倍;
4.用戶user1先抵押100個EOS,后面再抵押1000個EOS投票,如果用戶已投票,那么后面再做抵押的時候,用戶不用手動再進行投票,系統會自動把此次新增的抵押對應的選票數給用戶已投的節點;
5.如果用戶usr1給usr2抵押100EOS,usr2用這100 EOS來投票的話是無效的(沒有異常,但節點不會增加選票),只能是usr1有投票權;
注:投票對於用戶來說是沒有任何獎勵和好處的,相反會因此抵押EOS,贖回也需要三天時間。
二.RAM的交易
基本的介紹與概念可以參考:https://blog.csdn.net/w7849516230/article/details/80836913
在查看相關源代碼時主要有三個文件:
exchange_state.cpp eosio.system.cpp delegate_bandwidth.cpp
在源碼中由於convert是一個公共函數,有點繞,這里以買buyrambytes為例展開講一下。
首先,接口如下:
void system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) { //在數據庫中查找接口
auto itr = _rammarket.find(S(4,RAMCORE)); auto tmp = *itr;
//這里先計算出買 * bytes 內存需要多少EOS
auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );
//購買內存
buyram( payer, receiver, eosout );
}
extended_asset exchange_state::convert( extended_asset from, extended_symbol to ) { auto sell_symbol = from.get_extended_symbol(); auto ex_symbol = supply.get_extended_symbol(); auto base_symbol = base.balance.get_extended_symbol(); auto quote_symbol = quote.balance.get_extended_symbol(); if( sell_symbol != ex_symbol ) { if( sell_symbol == base_symbol ) { from = convert_to_exchange( base, from ); } else if( sell_symbol == quote_symbol ) { from = convert_to_exchange( quote, from ); } else { eosio_assert( false, "invalid sell" ); } } else { if( to == base_symbol ) { from = convert_from_exchange( base, from ); } else if( to == quote_symbol ) { from = convert_from_exchange( quote, from ); } else { eosio_assert( false, "invalid conversion" ); } } if( to != from.get_extended_symbol() ) return convert( from, to ); return from; }
convert是一個公共接口,這里多次比較是為了查看RAM,EOS,RERAM,三者之間相互轉換,先看看初始化的動作
system_contract::system_contract( account_name s ) :native(s), _voters(_self,_self), _producers(_self,_self), _global(_self,_self), _rammarket(_self,_self) { //print( "construct system\n" ); _gstate = _global.exists() ? _global.get() : get_default_parameters(); auto itr = _rammarket.find(S(4,RAMCORE)); if( itr == _rammarket.end() ) { auto system_token_supply = eosio::token(N(eosio.token)).get_supply(eosio::symbol_type(system_token_symbol).name()).amount; if( system_token_supply > 0 ) { itr = _rammarket.emplace( _self, [&]( auto& m ) { m.supply.amount = 100000000000000ll; m.supply.symbol = S(4,RAMCORE); m.base.balance.amount = int64_t(_gstate.free_ram()); m.base.balance.symbol = S(0,RAM); m.quote.balance.amount = system_token_supply / 1000; m.quote.balance.symbol = CORE_SYMBOL; }); } } else { //print( "ram market already created" ); } }
把類型和對應的整形簡單地區別一下,翻譯成如下對應:
supply S(4,RAMCORE)
base S(0,RAM)
quote S(4,SYS)
此時,再回到buyrambytes這個函數,發現那四個參數分別對應如下 :
sell_symbol S(0,RAM))
ex_symbol S(4,RAMCORE)
base_symbol S(0,RAM)
quote_symbol S(4,SYS)
此時再看convert接口邏輯一目了然,無非就是三者之間的換算關系和數據存儲。
其它的買賣和此原理一樣,自己看源碼或許是最好的選擇~
三.RAM的使用率
相關的源碼文件為resource_limits.cpp,函數為add_pending_ram_usage,所有內存的使用和釋放都通過此接口進行調用,以下操作會影響RAM的使用率:
1.增加內存:
- 延時交易
- 使用system newaccount創建帳戶
- 關聯權限(linkauth)
- 即時交易
- chainbase::database中數據表的創建或者數據的存儲操作
2.減少內存
- 取消延時交易
- 刪除子權限
- 取消關聯權限(unlinkauth)
- chainbase::database中數據的刪除操作
3.其它
- 更新合約(abi文件類似)
- 更新權限