以太坊交易处理流程

交易部分总结,好记性不如烂笔头
配合代码食用(Geth v1.9.0 stable)

整体流程

发起交易:设定fromtovaluegas等参数生成交易
交易签名:使用账户私钥对交易进行签名
提交交易:把交易加入到交易池txpool
广播交易:把交易信息广播给其他结点
处理交易:矿工取交易,EVM执行,改变状态

代码流程(全节点)

1.前端发起交易
2.internal/ethapi/api.go
  • PublicTransactionPoolAPI.SendTransaction,根据参数创建交易,签名,submitTransaction提交交易

  • PublicTransactionPoolAPI.SendRawTransaction,解码已签名交易,submitTransaction提交交易

  • PrivateAccountAPI.SendTransaction,根据参数创建签名交易,submitTransaction提交交易

  • submitTransaction,调用后端发送交易方法Backend.SendTx

3.eth/api_backend.go
  • Backend.SendTx,调用交易池添加交易到本地EthAPIBackend.eth.txPool.AddLocal(signedTx)
4.core/tx_pool.go

tip:TxPool包含pending(当前可执行交易队列)和queue(当前不可执行交易队列)两个交易队列,类型为map[common.Address]*txList

  • TxPool.AddLocal,调用TxPool.addTx将交易加入交易池(除AddLocal还有AddRemote,内部都调用TxPool.addTx,如果是local交易会写入本地磁盘日志中,在节点重启时加载恢复,在一些过滤操作中保留的优先级高)

  • TxPool.addTx内部调用TxPool.add,add方法进行一系列验证后将交易加入queue,用于后续提升至pending中去执行,具体逻辑包括:

    • 通过交易哈希验证是未知交易,如果交易池已包含该交易,return
    • TxPool.validateTx交易有效验证,验证不通过,return
    • 判断交易池已满时,判断如果交易手续费比当前交易池中手续费最低的交易还低,return,否则,移除一些交易以腾出空间
    • 判断交易池pending中包含相同from和nonce的交易时,比较gasPrice大于旧交易gasPrice且大于threshold*(门槛),则替换并协程发送事件进行广播 go TxPool.txFeed.Send(NewTxsEvent{types.Transactions{tx}}),否则return
    • 不是以上两种替换交易池中已有交易的情况,TxPool.enqueueTx将交易插入queue
    • 判断如果是local交易,记录并将交易写入本地磁盘日志中
  • add方法返回是否有替换交易(replace bool),如果为false,不是替换,仅仅是添加一个新的交易,执行参数为from的TxPool.promoteExecutables

  • TxPool.promoteExecutables方法把queue中变得可执行的交易转移到pending中,并删除所有无效交易,具体逻辑包括:

    • 创建临时变量交易列表promoted
    • 判断参数accounts(类型[]common.Address)是否为空,如果为空则赋值为queue中所有地址
    • 遍历accounts,取出key为addr的list,即from为addr的交易列表,在循环中:
      • 丢弃nonce比当前账户nonce低的交易
      • 丢弃交易花费超过账户余额和gas使用超出当前交易池可用gas的交易
      • 根据TxPool.pendingState的nonce值取出所有可执行的交易,执行TxPool.promoteTx将交易插入pending,如果插入成功则把交易加入到promoted
      • 如果addr不是本地账户,如果列表大小超过交易池中每个账户最多不可执行交易数量(默认64),丢弃
      • 如果列表已经为空,删除queue中addr这个key
    • 判断如果promoted大小大于0,协程发送事件进行广播 go pool.txFeed.Send(NewTxsEvent{promoted})
    • 判断如果pending中交易数量超出限制(4096),做平衡操作:创建集合记录交易数量超出限制的非本地账户,丢弃pending中这些账户下的部分交易直到数量不超过限制,更新TxPool.pendingState
    • 判断如果queue中交易数量超出限制(1024),取出非本地账户交易,根据心跳排序,丢弃交易直到数量不超过限制
  • 扩展,有TxPool.promoteExecutables还有TxPool.demoteUnexecutables,具体逻辑:

    • 遍历pending,得到addr下交易列表:
      • 丢弃nonce比当前账户nonce低的交易
      • 丢弃交易花费超过账户余额和gas使用超出当前交易池可用gas的交易,这些移除的交易最小的nonce为lowest,列表中nonce大于lowest的交易移除并加入临时列表invalids返回
      • 遍历invalids,调用TxPool.enqueueTx插入queue
      • 判断如果当前列表中找不到addr当前nonce对应的交易,从pending中移除列表中所有交易,调用TxPool.enqueueTx插入queue
      • pending和beats的key该删除的删除
    • 调用时机:在reset中调用,reset方法在NewTxPool和TxPool.loop中收到ChainHeadEvent时调用,在矿工worker.resultLoop收到resultCh和BlockChain.InsertChain后会PostChainEvents
5.在有新的交易插入pending时,广播NewTxsEvent,SubscribeNewTxsEvent方法用于监听到NewTxsEvent

调用时机:

  • ethstats/ethstats.go Start方法中开启loop协程,在该协程中订阅并处理,主要是通知交易事件,并在时间上过滤避免过于频繁的事件处理
  • eth/filters/filter_system.go
  • eth/handler.go ProtocolManager.Start方法中订阅(该方法会在节点启动时调用),go pm.txBroadcastLoop()开启协程处理,当收到NewTxsEvent,调用ProtocolManager.BroadcastTxs方法广播交易到其他所有没有该交易的节点
  • miner/worker.go newWorker方法中订阅,并开启了协程来处理,当收到NewTxsEvent
    • 判断如果节点不在挖矿,这里会立即调用worker.commitTransactions方法处理并更新快照,其中worker.commitTransactions方法核心逻辑是调用core.ApplyTransaction处理交易
    • 判断如果节点在挖矿,不处理
6.core/state_processor.go
  • ApplyTransaction方法,将Transaction转化为Message,创建evm,调用core/state_transition.go ApplyMessage执行Message,执行成功后更新状态,创建交易回执并返回
7.core/state_transition.go
  • ApplyMessage会创建一个StateTransition对象并调用其TransitionDb方法,该方法让虚拟机evm处理交易数据(创建合约或普通交易),并更新nonce,balance等状态

计算threshold(门槛),core/tx_list.go Add方法
old.gasprice
(100+priceBump)/100=threshold阙值

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容

  • 昨天晚上下起了大雨,大风呼呼的刮了一夜。今早上起床冷的很。本来昨天你还想穿背心来着。 中午接你,你说妈妈考试了,只...
    心若向阳无畏悲伤_阅读 156评论 0 0
  • 母亲一生勤劳,农村的活基本上没有不会干的,大部分的农活也都干过,甚至在大田里扶过犁,砌过墙……这些原本都是男...
    一坛老醋阅读 1,207评论 0 2
  • ① 来看这个房间的人都很惊讶,不过九平米的地方,平常活动已经不太方便,怎么还会把一整面墙做成镜子?他们总要仔细打量...
    野马失衡阅读 369评论 3 4
  • 那棵树真的很寂寞。 比我要寂寞许多。 12月的最后一天,树上仍然没有叶子,我不知道它还能活多久,或能不能活。 他说...
    田半阅读 598评论 1 8