Go-Ethereum

為什麼乙太坊在執行合約查詢時將使用者餘額設置為 MaxBig256?

  • September 13, 2019

執行合約呼叫時,使用者錢包餘額有一個奇怪的行為(應該沒有成本)。餘額是正確的(預期值),直到請求對合約進行免費呼叫。通過調試錢包餘額發現,錢包餘額總是在這一刻變成最大值。

乙太坊程式碼有一條可疑的線,這種奇怪的行為似乎來自:

eth\api_backend.go(135):
   state.SetBalance(msg.From(), math.MaxBig256)

它屬於 GetEVM() 函式:

func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
   ======> state.SetBalance(msg.From(), math.MaxBig256)
       vmError := func() error { return nil }

       context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil)
       return vm.NewEVM(context, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil
   }

這個平衡設置有什麼解釋嗎?它是協議的一部分嗎?有什麼提示嗎?多謝!

我閱讀了為什麼函式 GetEVM 將地址的餘額設置為 MaxBig256?

這是一個臨時的平衡設置,但我仍然不明白這種奇怪行為背後的邏輯。在我看來,呼叫合約時避免資金不足問題的程式碼很亂,對吧?

在乙太坊中,在 EVM 中執行操作需要消耗 gas。可以通過進行交易來改變區塊鏈中的任何狀態。在這種情況下,您將被收取乙太幣。為了進行交易,我們有一些像SendTransaction裡面的api

internal/ethapi/api.go

當您發送交易時,您可以設置 Gas 限制和 Gas 價格。您的餘額將根據進行更改所需的操作收取。

另外裡面還有一個api doCall

internal/ethapi/api.go

可以在任何方法上呼叫此 api。doCallSendTransaction之間的區別是 - 在 doCall 的情況下,區塊鏈中不會保留任何修改。如果您的solidity 函式返回一個值,您可以通過呼叫該函式而不是進行事務來檢索該值。

所以現在來到問題的重點。當一個函式呼叫doCall api 時,雖然它不會在區塊鏈中持久化任何更改,但它需要 gas 來臨時執行記憶體中的更改。因此,它呼叫GetEVM從(內部)獲取 EVM

internal/ethapi/backend.go

由於該doCall將在 EVM 中執行操作,因此它暫時需要呼叫****doCall操作的帳戶中的餘額。因此,為from帳戶臨時設置了最大整數值,以便它可以執行操作而不管其餘額如何。

另一件事在這裡很重要,當在裡面呼叫SetBalance api時

core/state/statedb.go

它只是保存記憶體中的更改。它不會保留區塊鏈狀態中的餘額變化。通過內部呼叫Commit函式送出保存在記憶體中的更改,將塊插入鏈中時,更改將持久保存在區塊鏈中

core/state/statedb.go

在使用WriteBlockWithState api 在鏈中插入塊時

core/blockchain.go

因此,得出的結論是 - SetBalance 不會持續鏈中的餘額變化。與 doCall 的情況一樣,它沒有事務效果。所以平衡的變化永遠不會在鏈中被送出。

希望它可以幫助您理解基本概念。

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