1、数据库中账户余额增减角度逆推
======================
func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction)
func (b *BlockGen) AddTx(tx *types.Transaction)
ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
======================
-----------
func (b *SimulatedBackend) Commit()
b.blockchain.InsertChain([]*types.Block{b.pendingBlock})
-----------
func (bc *BlockChain) procFutureBlocks()
bc.InsertChain(blocks[i : i+1])
-----------
func newCanonical(n int, full bool)
blockchain.InsertChain(blocks)
-----------
func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, blockchainId, networkId uint64, maxPeers int, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database)
manager.blockchain.InsertChain(blocks)
-----------
go worker.wait()
self.chain.InsertChain(types.Blocks{block})
-----------
func (bc *BlockChain) InsertChain(chain types.Blocks)
bc.processor.Process(block, state, bc.vmConfig)
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config)
ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, totalUsedGas, cfg)
=======================
-----------
*******
fullNode, err := eth.New(ctx, cfg)
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error)
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)
newWorker(config, engine, common.Address{}, eth, mux)
go worker.update() + go worker.wait() + worker.commitNewWork()
self.commitNewWork()
*******
^^^^^^^
func startNode(ctx *cli.Context, stack *node.Node)
ethereum.StartMining(true)
+++++++
func (api *PrivateMinerAPI) Start(threads *int)
api.e.StartMining(true)
+++++++
func (s *Ethereum) StartMining(local bool)
go s.miner.Start(eb)
^^^^^^^
fullNode, err := eth.New(ctx, cfg)
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error)
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)
go miner.update()
func (self *Miner) update()
self.Start(self.coinbase)
^^^^^^^
func (self *Miner) Start(coinbase common.Address)
self.worker.commitNewWork()
*******
func (self *worker) commitNewWork()
work.commitTransactions(self.mux, txs, self.chain, self.coinbase)
-----------
...
newWorker(config, engine, common.Address{}, eth, mux)
go worker.update()
self.current.commitTransactions(self.mux, txset, self.chain, self.coinbase)
-----------
func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsByPriceAndNonce, bc *core.BlockChain, coinbase common.Address)
env.commitTransaction(tx, bc, coinbase, gp)
ApplyTransaction(env.config, bc, &coinbase, gp, env.state, env.header, tx, env.header.GasUsed, vm.Config{})
==============
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config)
ApplyMessage(vmenv, msg, gp)
st.TransitionDb()
evm.Call(sender, st.to().Address(), st.data, st.gas, st.value)
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
db.SubBalance(sender, amount)
db.AddBalance(recipient, amount)
}
db.SubBalance(sender, amount) >> StateDb.SubBalance(sender, amount) >> stateObject.SubBalance(amount) >> c.SetBalance(new(big.Int).Sub(c.Balance(), amount)) >> stateObject.SetBalance(amount) >> stateObject.setBalance(amount)
db.AddBalance(recipient, amount) >> StateDB.AddBalance(recipient, amount) >> stateObject.AddBalance(amount) >> c.SetBalance(new(big.Int).Add(c.Balance(), amount)) >> stateObject.SetBalance(amount) >> stateObject.setBalance(amount)
2、命令行产生交易操作流程
eth.sendTransaction()
func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs)
submitTransaction(ctx, s.b, signed)
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction)
b.SendTx(ctx, tx) >> func (b *EthApiBackend) SendTx((ctx, tx) >> b.eth.txPool.AddLocal(signedTx) >> pool.addTx(tx, !pool.config.NoLocals) >> pool.add(tx, local)
=============================
personal.sendTransaction()
func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string)
submitTransaction(ctx, s.b, signed)
3、交易传递、广播
ProtocolManager.Start()
go pm.txBroadcastLoop()
self.BroadcastTx(event.Tx.Hash(), event.Tx)
peer.SendTransactions(types.Transactions{tx})
p2p.Send(p.rw, TxMsg, txs)
===================
------
newPool := core.NewTxPool(config.TxPool, eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
go pool.eventLoop() ==>顺序执行 pool.resetState()
pool.resetState()
func (pool *TxPool) resetState()
pool.promoteExecutables(currentState, nil)
------
******
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) >> b.SendTx(ctx, tx)
func (b *EthApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
b.eth.txPool.AddLocal(signedTx)
pool.addTx(tx, !pool.config.NoLocals)
******
func (pool *TxPool) AddRemote(tx *types.Transaction),没有被调用,仅用于测试
pool.addTx(tx, false)
******
func (pool *TxPool) addTx(tx *types.Transaction, local bool)
pool.promoteExecutables(state, []common.Address{from})
------
******
fullNode, err := eth.New(ctx, cfg)
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error)
newPool := core.NewTxPool(config.TxPool, eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
go pool.eventLoop()
pool.addTxs(ev.Txs, false)
******
func (pool *TxPool) AddLocals(txs []*types.Transaction),没有被调用,仅用于测试
pool.addTxs(txs, !pool.config.NoLocals)
******
func (pm *ProtocolManager) handleMsg(p *peer)的case msg.Code == TxMsg分支,执行pm.txpool.AddRemotes(txs)
func (pool *TxPool) AddRemotes(txs []*types.Transaction)
pool.addTxs(txs, false)
******
func (pool *TxPool) addTxs(txs []*types.Transaction, local bool)
pool.promoteExecutables(state, addrs)
------
func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.Address)
pool.promoteTx(addr, hash, tx)
go pool.eventMux.Post(TxPreEvent{tx})
sub.deliver(event) >> s.postC <- event, postC <=> readC
func (s *TypeMuxSubscription) Chan() <-chan *TypeMuxEvent { return s.readC }
Chan()方法在txBroadcastLoop()中被调用,进一步触发BroadcastTx(),然后将TxMsg广播出去,这是最重要的功能
Chan()方法在worker.update()中被调用,在TxPreEvent分支,进一步触发`Apply transaction to the pending state if we're not mining`相关操作,其中包含self.current.commitTransactions(self.mux, txset, self.chain, self.coinbase)
Chan()方法在EventSystem.eventLoop()中被调用,进一步触发es.broadcast(index, ev)