github.com/codingfuture/orig-energi3@v0.8.4/energi/consensus/blacklist.go (about) 1 // Copyright 2019 The Energi Core Authors 2 // This file is part of the Energi Core library. 3 // 4 // The Energi Core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The Energi Core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package consensus 18 19 import ( 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/core" 22 "github.com/ethereum/go-ethereum/core/state" 23 "github.com/ethereum/go-ethereum/core/types" 24 "github.com/ethereum/go-ethereum/log" 25 26 energi_params "energi.world/core/gen3/energi/params" 27 ) 28 29 var ( 30 blacklistValue = common.BytesToHash([]byte{0x01}) 31 ) 32 33 func (e *Energi) processBlacklists( 34 chain ChainReader, 35 header *types.Header, 36 statedb *state.StateDB, 37 ) (err error) { 38 blregistry := energi_params.Energi_BlacklistRegistry 39 40 enumerateData, err := e.blacklistAbi.Pack("enumerateBlocked") 41 if err != nil { 42 log.Error("Fail to prepare enumerateBlocked() call", "err", err) 43 return err 44 } 45 46 msg := types.NewMessage( 47 blregistry, 48 &blregistry, 49 0, 50 common.Big0, 51 e.unlimitedGas, 52 common.Big0, 53 enumerateData, 54 false, 55 ) 56 rev_id := statedb.Snapshot() 57 evm := e.createEVM(msg, chain, header, statedb) 58 gp := core.GasPool(e.unlimitedGas) 59 output, gas_used, _, err := core.ApplyMessage(evm, msg, &gp) 60 statedb.RevertToSnapshot(rev_id) 61 if err != nil { 62 log.Error("Failed in enumerateBlocked() call", "err", err) 63 return err 64 } 65 66 if gas_used > e.callGas { 67 log.Warn("BlacklistRegistry::enumerateDrainable() took excessive gas", 68 "gas", gas_used, "limit", e.callGas) 69 } 70 71 address_list := new([]common.Address) 72 err = e.blacklistAbi.Unpack(&address_list, "enumerateBlocked", output) 73 if err != nil { 74 log.Error("Failed to unpack enumerateBlocked() call", "err", err) 75 return err 76 } 77 78 log.Debug("Address blacklist", "address_list", address_list) 79 empty_addr := common.Address{} 80 state_obj := statedb.GetOrNewStateObject(energi_params.Energi_Blacklist) 81 db := statedb.Database() 82 keep := make(state.KeepStorage, len(*address_list)) 83 whitelist := e.createWhitelist(statedb) 84 85 for _, addr := range *address_list { 86 if addr != empty_addr && !whitelist[addr] { 87 addr_hash := addr.Hash() 88 89 if (state_obj.GetState(db, addr_hash) == common.Hash{}) { 90 log.Debug("New blacklisted account", "addr", addr) 91 } 92 93 log.Trace("Blacklisting account", "addr", addr) 94 state_obj.SetState(db, addr_hash, blacklistValue) 95 keep[addr_hash] = true 96 } 97 } 98 99 state_obj.CleanupStorage(keep) 100 101 // 102 wl_state_obj := statedb.GetOrNewStateObject(energi_params.Energi_Whitelist) 103 wl_keep := make(state.KeepStorage, len(whitelist)) 104 for addr := range whitelist { 105 addr_hash := addr.Hash() 106 107 if (wl_state_obj.GetState(db, addr_hash) == common.Hash{}) { 108 log.Debug("New whitelisted account", "addr", addr) 109 } 110 111 log.Trace("Whitelisting account", "addr", addr) 112 wl_state_obj.SetState(db, addr_hash, blacklistValue) 113 wl_keep[addr_hash] = true 114 } 115 116 wl_state_obj.CleanupStorage(wl_keep) 117 118 return nil 119 } 120 121 var ( 122 consensusProxies = []common.Address{ 123 energi_params.Energi_Treasury, 124 energi_params.Energi_MasternodeRegistry, 125 energi_params.Energi_StakerReward, 126 energi_params.Energi_BackboneReward, 127 energi_params.Energi_SporkRegistry, 128 energi_params.Energi_CheckpointRegistry, 129 energi_params.Energi_BlacklistRegistry, 130 energi_params.Energi_MasternodeToken, 131 } 132 133 consensusStandalone = []common.Address{ 134 energi_params.Energi_MigrationContract, 135 energi_params.Energi_SystemFaucet, 136 } 137 ) 138 139 func (e *Energi) createWhitelist( 140 statedb *state.StateDB, 141 ) map[common.Address]bool { 142 whitelist := map[common.Address]bool{} 143 144 for _, addr := range consensusProxies { 145 whitelist[addr] = true 146 impl := statedb.GetState(addr, energi_params.Storage_ProxyImpl) 147 whitelist[common.BytesToAddress(impl[:])] = true 148 } 149 150 for _, addr := range consensusStandalone { 151 whitelist[addr] = true 152 } 153 154 return whitelist 155 } 156 157 func (e *Energi) processDrainable( 158 chain ChainReader, 159 header *types.Header, 160 statedb *state.StateDB, 161 txs types.Transactions, 162 receipts types.Receipts, 163 ) (types.Transactions, types.Receipts, error) { 164 blregistry := energi_params.Energi_BlacklistRegistry 165 var comp_fund common.Address 166 167 txhash := common.Hash{} 168 bhash := header.Hash() 169 statedb.Prepare(txhash, bhash, len(txs)) 170 171 // 1. List drainable addresses address 172 //--- 173 enumerateData, err := e.blacklistAbi.Pack("enumerateDrainable") 174 if err != nil { 175 log.Error("Fail to prepare enumerateDrainable() call", "err", err) 176 return nil, nil, err 177 } 178 179 msg := types.NewMessage( 180 blregistry, 181 &blregistry, 182 0, 183 common.Big0, 184 e.unlimitedGas, 185 common.Big0, 186 enumerateData, 187 false, 188 ) 189 rev_id := statedb.Snapshot() 190 evm := e.createEVM(msg, chain, header, statedb) 191 gp := core.GasPool(e.unlimitedGas) 192 output, gas_used, _, err := core.ApplyMessage(evm, msg, &gp) 193 statedb.RevertToSnapshot(rev_id) 194 if err != nil { 195 log.Error("Failed in enumerateDrainable() call", "err", err) 196 return nil, nil, err 197 } 198 199 if gas_used > e.callGas { 200 log.Warn("BlacklistRegistry::enumerateDrainable() took excessive gas", 201 "gas", gas_used, "limit", e.callGas) 202 } 203 204 address_list := new([]common.Address) 205 err = e.blacklistAbi.Unpack(&address_list, "enumerateDrainable", output) 206 if err != nil { 207 log.Error("Failed to unpack enumerateDrainable() call", "err", err) 208 return nil, nil, err 209 } 210 211 log.Debug("Address drain list", "address_list", address_list) 212 213 // 2. Get current compensation fund address 214 if len(*address_list) > 0 { 215 enumerateData, err := e.blacklistAbi.Pack("compensation_fund") 216 if err != nil { 217 log.Error("Fail to prepare compensation_fund() call", "err", err) 218 return nil, nil, err 219 } 220 221 msg := types.NewMessage( 222 blregistry, 223 &blregistry, 224 0, 225 common.Big0, 226 e.callGas, 227 common.Big0, 228 enumerateData, 229 false, 230 ) 231 rev_id := statedb.Snapshot() 232 evm := e.createEVM(msg, chain, header, statedb) 233 gp = core.GasPool(e.callGas) 234 output, _, _, err := core.ApplyMessage(evm, msg, &gp) 235 statedb.RevertToSnapshot(rev_id) 236 if err != nil { 237 log.Error("Failed in compensation_fund() call", "err", err) 238 return nil, nil, err 239 } 240 241 err = e.blacklistAbi.Unpack(&comp_fund, "compensation_fund", output) 242 if err != nil { 243 log.Error("Failed to unpack compensation_fund() call", "err", err) 244 return nil, nil, err 245 } 246 } 247 248 // 3. Drain 249 //--- 250 empty_addr := common.Address{} 251 252 for _, addr := range *address_list { 253 if addr == empty_addr { 254 continue 255 } 256 257 //-- 258 bal := statedb.GetBalance(addr) 259 260 // Skip, if nothing 261 if bal.Cmp(common.Big0) == 0 { 262 continue 263 } 264 265 // Skip whitelisted 266 if core.CanTransfer(statedb, addr, bal) { 267 continue 268 } 269 270 log.Trace("Draining account", "fund", comp_fund, "addr", addr, "bal", bal) 271 272 //==================================== 273 contributeData, err := e.treasuryAbi.Pack("contribute") 274 if err != nil { 275 log.Error("Fail to prepare contribute() call", "err", err) 276 return nil, nil, err 277 } 278 279 tx := types.NewTransaction( 280 statedb.GetNonce(addr), 281 comp_fund, 282 bal, 283 e.xferGas, 284 common.Big0, 285 contributeData) 286 tx = tx.WithConsensusSender(addr) 287 288 statedb.Prepare(tx.Hash(), bhash, len(txs)) 289 290 msg, err = tx.AsMessage(&ConsensusSigner{}) 291 if err != nil { 292 log.Error("Failed in onDrain() msg", "err", err) 293 return nil, nil, err 294 } 295 296 statedb.SetState(energi_params.Energi_Blacklist, addr.Hash(), common.Hash{}) 297 evm = e.createEVM(msg, chain, header, statedb) 298 gp = core.GasPool(msg.Gas()) 299 _, gas1, failed, err := core.ApplyMessage(evm, msg, &gp) 300 statedb.SetState(energi_params.Energi_Blacklist, addr.Hash(), blacklistValue) 301 302 if err != nil { 303 log.Error("Failed in onDrain() call", "err", err) 304 return nil, nil, err 305 } 306 307 root := statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 308 receipt := types.NewReceipt(root.Bytes(), failed, header.GasUsed) 309 receipt.TxHash = tx.Hash() 310 receipt.GasUsed = gas1 311 receipt.Logs = statedb.GetLogs(tx.Hash()) 312 receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) 313 314 txs = append(txs, tx) 315 receipts = append(receipts, receipt) 316 317 //==================================== 318 collectData, err := e.blacklistAbi.Pack("onDrain", addr) 319 if err != nil { 320 log.Error("Fail to prepare onDrain() call", "err", err, "addr", addr) 321 return nil, nil, err 322 } 323 324 tx = types.NewTransaction( 325 statedb.GetNonce(blregistry), 326 blregistry, 327 common.Big0, 328 e.xferGas, 329 common.Big0, 330 collectData) 331 tx = tx.WithConsensusSender(blregistry) 332 333 statedb.Prepare(tx.Hash(), bhash, len(txs)) 334 335 msg, err = tx.AsMessage(&ConsensusSigner{}) 336 if err != nil { 337 log.Error("Failed in onDrain() msg", "err", err) 338 return nil, nil, err 339 } 340 341 evm = e.createEVM(msg, chain, header, statedb) 342 gp = core.GasPool(msg.Gas()) 343 _, gas2, failed, err := core.ApplyMessage(evm, msg, &gp) 344 if err != nil { 345 log.Error("Failed in onDrain() call", "err", err) 346 return nil, nil, err 347 } 348 349 root = statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 350 receipt = types.NewReceipt(root.Bytes(), failed, header.GasUsed) 351 receipt.TxHash = tx.Hash() 352 receipt.GasUsed = gas2 353 receipt.Logs = statedb.GetLogs(tx.Hash()) 354 receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) 355 356 txs = append(txs, tx) 357 receipts = append(receipts, receipt) 358 } 359 360 return txs, receipts, nil 361 }