本文基于geth 1.8.19的代码
pragma solidity ^0.4.20; |
- 代码
- 调用getCount的rpc代码入口
rpc/server.go
func (s *Server) serveRequest(ctx context.Context, codec ServerCodec, singleShot bool, options CodecOption) error { // 通过rpc过来的调用view,pure函数的入口走到这里
|
// exec executes the given request and writes the result back using the codec. if callback != nil {
|
// handle executes a request and returns the response from the callback. // 通过反射调用publicBlock的api |
// Call executes the given transaction on the state for the given block number. |
其中
PublicBlockChainAPI的定义如下:
// PublicBlockChainAPI provides an API to access the Ethereum blockchain. Backend位于ethapi/backend.go中 type Backend interface { |
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) { // 设置初始gas 2~63 以及gasPrice 1~9 // 因为调用evm的指令时候,需要消耗gas // 因为这个调用时免费的,所以这个gas最终并没什么用 // 初始化调用信息,包括 from,to, nonce,以及以太币份额,gasLimit,gasPrice,data // from , to , nonce , amount ,gasLimit, gasPrice, data , checkNonce msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false) // Setup context so it may be cancelled the call has completed // or, in case of unmetered gas, setup a context with a timeout. var cancel context.CancelFunc if timeout > 0 { ctx, cancel = context.WithTimeout(ctx, timeout) } else { ctx, cancel = context.WithCancel(ctx) } // Make sure the context is cancelled when the call has completed // this makes sure resources are cleaned up. defer cancel() // Get a new instance of the EVM. // 获取新的EVM evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg) if err != nil { return nil, 0, false, err } // Wait for the context to be done and cancel the evm. Even if the // EVM has finished, cancelling may be done (repeatedly) go func() { <-ctx.Done() evm.Cancel() }() // Setup the gas pool (also for unmetered requests) // and apply the message. // 初始化gas池,也适用于未确定的请求 gp := new(core.GasPool).AddGas(math.MaxUint64) // 执行一条事务代码 res, gas, failed, err := core.ApplyMessage(evm, msg, gp) if err := vmError(); err != nil { return nil, 0, false, err } return res, gas, failed, err }
|
-
-
-
- GetEVM获取以太坊EVM环境
-
-
代码位于eth/api_backend.go中
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmCfg vm.Config) (*vm.EVM, func() error, error) { |
-
-
-
- NewEVM(指定执行的指令解释器版本)
-
-
// NewEVM returns a new EVM. The returned EVM is not thread safe and should // 加载解释器 |
-
-
-
- NewEVMInterpreter加载解释器
-
-
core/vm/interpreter.go,根据配置文件,加载不同的解释器
包括拜赞庭版本,家园版本等,就是不同版本支持不同的指令。
// NewEVMInterpreter returns a new instance of the Interpreter. |
eg:
比如以下配置了constantinopleBlock,表示支持拜赞庭分支,该分支会多出几个指令,如STATICCALL,RETURNDATASIZE,RETURNDATACOPY具体支持的指令见:
core/vm/jump_table.go 中的 newByzantiumInstructionSet
{ "nonce": "0xdeadbeefdeadbeef", "alloc": {}, "timestamp": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "extraData": "", "gasLimit": "0xffffffffffffffff", "difficulty": "0x0000000000000000000000000000000000000000000000000000000000000001", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "config": { "constantinopleBlock": 0, "chainId": 8888888 } } |
-
-
-
- core/types/transaction.go 中的message定义
-
-
type Message struct {
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message { |
执行evm指令
// ApplyMessage computes the new state by applying the given message |
StateTransition数据结构
type StateTransition struct { |
// TransitionDb will transition the state by applying the current message and // to 即为合约地址 |
-
-
-
- 其中IntrinsicGas
-
-
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data. |
-
-
-
- refundGas
-
-
将一半花费的gas退还给交易的发起者,不知道为什么这么做
func (st *StateTransition) refundGas() { |
// Call executes the contract associated with the addr with the given input as |
-
-
-
- CanTransfer
-
-
// CanTransfer checks whether there are enough funds in the address' account to make a transfer. |
-
-
-
- Transfer
-
-
// Transfer subtracts amount from sender and adds amount to recipient using the given Db // todo 需要分析下,是先调用EVM再转账,还是先转账再调用EVM |
// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. |
// Run loops and evaluates the contract's code with the given input data and returns |
DEBUG[01-06|20:21:53.262|eth/downloader/downloader.go:1690] Recalculated downloader QoS values rtt=20s confidence=1.000 ttl=1m0s |
-
- increment调用栈信息(修改)
goroutine 53 [running]: |
runtime/debug.Stack(0xf8a880, 0x16, 0x4) |
rpc源码分析
区块和交易,合约和虚拟机
https://blog.csdn.net/teaspring/article/details/75389151
go-ethereum以太坊源码解析完整版
https://blog.csdn.net/luckydog612/article/details/80534758