|
@@ -36,21 +36,26 @@ import (
|
|
|
|
|
|
|
|
const (
|
|
const (
|
|
|
// chainHeadChanSize is the size of channel listening to ChainHeadEvent.
|
|
// chainHeadChanSize is the size of channel listening to ChainHeadEvent.
|
|
|
|
|
+ // ChainHeadEvent 事件的监听通道的大小。
|
|
|
chainHeadChanSize = 10
|
|
chainHeadChanSize = 10
|
|
|
|
|
|
|
|
// txSlotSize is used to calculate how many data slots a single transaction
|
|
// txSlotSize is used to calculate how many data slots a single transaction
|
|
|
// takes up based on its size. The slots are used as DoS protection, ensuring
|
|
// takes up based on its size. The slots are used as DoS protection, ensuring
|
|
|
// that validating a new transaction remains a constant operation (in reality
|
|
// that validating a new transaction remains a constant operation (in reality
|
|
|
// O(maxslots), where max slots are 4 currently).
|
|
// O(maxslots), where max slots are 4 currently).
|
|
|
|
|
+ //根据交易的大小计算单个交易占用的数据插槽数量。
|
|
|
|
|
+ //插槽用作防止拒绝服务(DoS)攻击的保护措施,确保验证新交易仍然是一个恒定的操作(实际上是 O(maxslots),其中 max slots 目前为 4)。
|
|
|
txSlotSize = 32 * 1024
|
|
txSlotSize = 32 * 1024
|
|
|
|
|
|
|
|
// txMaxSize is the maximum size a single transaction can have. This field has
|
|
// txMaxSize is the maximum size a single transaction can have. This field has
|
|
|
// non-trivial consequences: larger transactions are significantly harder and
|
|
// non-trivial consequences: larger transactions are significantly harder and
|
|
|
// more expensive to propagate; larger transactions also take more resources
|
|
// more expensive to propagate; larger transactions also take more resources
|
|
|
// to validate whether they fit into the pool or not.
|
|
// to validate whether they fit into the pool or not.
|
|
|
|
|
+ //单个交易的最大大小。这个字段有着重要的影响:较大的交易在传播时更难且更昂贵;较大的交易也需要更多的资源来验证它们是否适合进入交易池。
|
|
|
txMaxSize = 4 * txSlotSize // 128KB
|
|
txMaxSize = 4 * txSlotSize // 128KB
|
|
|
|
|
|
|
|
// txReannoMaxNum is the maximum number of transactions a reannounce action can include.
|
|
// txReannoMaxNum is the maximum number of transactions a reannounce action can include.
|
|
|
|
|
+ //重新公告(reannounce)操作中可以包含的最大交易数量。
|
|
|
txReannoMaxNum = 1024
|
|
txReannoMaxNum = 1024
|
|
|
)
|
|
)
|
|
|
|
|
|
|
@@ -89,36 +94,57 @@ var (
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
var (
|
|
|
- evictionInterval = time.Minute // Time interval to check for evictable transactions
|
|
|
|
|
|
|
+ //在每个时间间隔内,交易池会检查是否有过期的交易,并进行驱逐操作。
|
|
|
|
|
+ evictionInterval = time.Minute // Time interval to check for evictable transactions
|
|
|
|
|
+ //交易池统计报告的时间间隔。在每个时间间隔内,交易池会生成并报告交易池的统计信息。
|
|
|
statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats
|
|
statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats
|
|
|
- reannounceInterval = time.Minute // Time interval to check for reannounce transactions
|
|
|
|
|
|
|
+ //检查重新广播(reannounce)交易的时间间隔。在每个时间间隔内,交易池会检查是否有需要重新广播的交易,并进行相应的处理。
|
|
|
|
|
+ reannounceInterval = time.Minute // Time interval to check for reannounce transactions
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
var (
|
|
|
// Metrics for the pending pool
|
|
// Metrics for the pending pool
|
|
|
- pendingDiscardMeter = metrics.NewRegisteredMeter("txpool/pending/discard", nil)
|
|
|
|
|
- pendingReplaceMeter = metrics.NewRegisteredMeter("txpool/pending/replace", nil)
|
|
|
|
|
- pendingRateLimitMeter = metrics.NewRegisteredMeter("txpool/pending/ratelimit", nil) // Dropped due to rate limiting
|
|
|
|
|
- pendingNofundsMeter = metrics.NewRegisteredMeter("txpool/pending/nofunds", nil) // Dropped due to out-of-funds
|
|
|
|
|
|
|
+ // pendingDiscardMeter 计量已决交易被丢弃的数量
|
|
|
|
|
+ pendingDiscardMeter = metrics.NewRegisteredMeter("txpool/pending/discard", nil)
|
|
|
|
|
+ // pendingReplaceMeter 计量已决交易被替换的数量
|
|
|
|
|
+ pendingReplaceMeter = metrics.NewRegisteredMeter("txpool/pending/replace", nil)
|
|
|
|
|
+ // pendingRateLimitMeter 计量由于速率限制而被丢弃的已决交易的数量
|
|
|
|
|
+ pendingRateLimitMeter = metrics.NewRegisteredMeter("txpool/pending/ratelimit", nil)
|
|
|
|
|
+ // pendingNofundsMeter 计量由于资金不足而被丢弃的已决交易的数量
|
|
|
|
|
+ pendingNofundsMeter = metrics.NewRegisteredMeter("txpool/pending/nofunds", nil)
|
|
|
|
|
|
|
|
// Metrics for the queued pool
|
|
// Metrics for the queued pool
|
|
|
- queuedDiscardMeter = metrics.NewRegisteredMeter("txpool/queued/discard", nil)
|
|
|
|
|
- queuedReplaceMeter = metrics.NewRegisteredMeter("txpool/queued/replace", nil)
|
|
|
|
|
- queuedRateLimitMeter = metrics.NewRegisteredMeter("txpool/queued/ratelimit", nil) // Dropped due to rate limiting
|
|
|
|
|
- queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds
|
|
|
|
|
- queuedEvictionMeter = metrics.NewRegisteredMeter("txpool/queued/eviction", nil) // Dropped due to lifetime
|
|
|
|
|
|
|
+ // queuedDiscardMeter 计量排队交易被丢弃的数量
|
|
|
|
|
+ queuedDiscardMeter = metrics.NewRegisteredMeter("txpool/queued/discard", nil)
|
|
|
|
|
+ // queuedReplaceMeter 计量排队交易被替换的数量
|
|
|
|
|
+ queuedReplaceMeter = metrics.NewRegisteredMeter("txpool/queued/replace", nil)
|
|
|
|
|
+ // queuedRateLimitMeter 计量由于速率限制而被丢弃的排队交易的数量
|
|
|
|
|
+ queuedRateLimitMeter = metrics.NewRegisteredMeter("txpool/queued/ratelimit", nil)
|
|
|
|
|
+ // queuedNofundsMeter 计量由于资金不足而被丢弃的排队交易的数量
|
|
|
|
|
+ queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil)
|
|
|
|
|
+ // queuedEvictionMeter 计量由于生命周期结束而被丢弃的排队交易的数量
|
|
|
|
|
+ queuedEvictionMeter = metrics.NewRegisteredMeter("txpool/queued/eviction", nil)
|
|
|
|
|
|
|
|
// General tx metrics
|
|
// General tx metrics
|
|
|
- knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil)
|
|
|
|
|
- validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil)
|
|
|
|
|
- invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil)
|
|
|
|
|
|
|
+ // knownTxMeter 计量已知交易的数量
|
|
|
|
|
+ knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil)
|
|
|
|
|
+ // validTxMeter 计量有效交易的数量
|
|
|
|
|
+ validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil)
|
|
|
|
|
+ // invalidTxMeter 计量无效交易的数量
|
|
|
|
|
+ invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil)
|
|
|
|
|
+ // underpricedTxMeter 计量低价交易的数量
|
|
|
underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil)
|
|
underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil)
|
|
|
- overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil)
|
|
|
|
|
|
|
+ // overflowedTxMeter 计量溢出交易的数量
|
|
|
|
|
+ overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil)
|
|
|
|
|
|
|
|
|
|
+ // pendingGauge 计量当前已决交易的数量
|
|
|
pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil)
|
|
pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil)
|
|
|
- queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil)
|
|
|
|
|
- localGauge = metrics.NewRegisteredGauge("txpool/local", nil)
|
|
|
|
|
- slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil)
|
|
|
|
|
|
|
+ // queuedGauge 计量当前排队交易的数量
|
|
|
|
|
+ queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil)
|
|
|
|
|
+ // localGauge 计量当前本地交易的数量
|
|
|
|
|
+ localGauge = metrics.NewRegisteredGauge("txpool/local", nil)
|
|
|
|
|
+ // slotsGauge 计量当前交易占用的数据槽位数量
|
|
|
|
|
+ slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil)
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// TxStatus is the current status of a transaction as seen by the pool.
|
|
// TxStatus is the current status of a transaction as seen by the pool.
|
|
@@ -141,23 +167,23 @@ type blockChain interface {
|
|
|
SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription
|
|
SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// TxPoolConfig are the configuration parameters of the transaction pool.
|
|
|
|
|
|
|
+// TxPoolConfig 是交易池的配置参数。
|
|
|
type TxPoolConfig struct {
|
|
type TxPoolConfig struct {
|
|
|
- Locals []common.Address // Addresses that should be treated by default as local
|
|
|
|
|
- NoLocals bool // Whether local transaction handling should be disabled
|
|
|
|
|
- Journal string // Journal of local transactions to survive node restarts
|
|
|
|
|
- Rejournal time.Duration // Time interval to regenerate the local transaction journal
|
|
|
|
|
|
|
+ Locals []common.Address // 默认情况下应被视为本地交易的地址列表
|
|
|
|
|
+ NoLocals bool // 是否禁用本地交易处理
|
|
|
|
|
+ Journal string // 本地交易日志,用于在节点重启后恢复
|
|
|
|
|
+ Rejournal time.Duration // 重新生成本地交易日志的时间间隔
|
|
|
|
|
|
|
|
- PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool
|
|
|
|
|
- PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce)
|
|
|
|
|
|
|
+ PriceLimit uint64 // 最小的 gas 价格以确保交易被接受到交易池中
|
|
|
|
|
+ PriceBump uint64 // 用于替换已存在交易的最小价格增幅百分比(按 nonce 排序)
|
|
|
|
|
|
|
|
- AccountSlots uint64 // Number of executable transaction slots guaranteed per account
|
|
|
|
|
- GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts
|
|
|
|
|
- AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account
|
|
|
|
|
- GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts
|
|
|
|
|
|
|
+ AccountSlots uint64 // 每个账户保证的可执行交易槽位数量
|
|
|
|
|
+ GlobalSlots uint64 // 所有账户可执行交易槽位的最大数量
|
|
|
|
|
+ AccountQueue uint64 // 每个账户允许的非可执行交易槽位的最大数量
|
|
|
|
|
+ GlobalQueue uint64 // 所有账户非可执行交易槽位的最大数量
|
|
|
|
|
|
|
|
- Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
|
|
|
|
|
- ReannounceTime time.Duration // Duration for announcing local pending transactions again
|
|
|
|
|
|
|
+ Lifetime time.Duration // 非可执行交易在排队中的最大时间
|
|
|
|
|
+ ReannounceTime time.Duration // 本地已决交易再次宣布的时间间隔
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DefaultTxPoolConfig contains the default configurations for the transaction
|
|
// DefaultTxPoolConfig contains the default configurations for the transaction
|
|
@@ -221,39 +247,37 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig {
|
|
|
return conf
|
|
return conf
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// TxPool contains all currently known transactions. Transactions
|
|
|
|
|
-// enter the pool when they are received from the network or submitted
|
|
|
|
|
-// locally. They exit the pool when they are included in the blockchain.
|
|
|
|
|
|
|
+// TxPool 包含了当前已知的所有交易。当交易从网络接收或本地提交时,它们会进入交易池。
|
|
|
|
|
+// 当交易被包含在区块链中时,它们会从交易池中移除。
|
|
|
//
|
|
//
|
|
|
-// The pool separates processable transactions (which can be applied to the
|
|
|
|
|
-// current state) and future transactions. Transactions move between those
|
|
|
|
|
-// two states over time as they are received and processed.
|
|
|
|
|
|
|
+// 交易池将交易分为可处理交易(可应用于当前状态)和未来交易。
|
|
|
|
|
+// 随着交易的接收和处理,交易会在这两种状态之间移动。
|
|
|
type TxPool struct {
|
|
type TxPool struct {
|
|
|
config TxPoolConfig
|
|
config TxPoolConfig
|
|
|
chainconfig *params.ChainConfig
|
|
chainconfig *params.ChainConfig
|
|
|
chain blockChain
|
|
chain blockChain
|
|
|
gasPrice *big.Int
|
|
gasPrice *big.Int
|
|
|
txFeed event.Feed
|
|
txFeed event.Feed
|
|
|
- reannoTxFeed event.Feed // Event feed for announcing transactions again
|
|
|
|
|
|
|
+ reannoTxFeed event.Feed // 用于重新宣布交易的事件订阅
|
|
|
scope event.SubscriptionScope
|
|
scope event.SubscriptionScope
|
|
|
signer types.Signer
|
|
signer types.Signer
|
|
|
mu sync.RWMutex
|
|
mu sync.RWMutex
|
|
|
|
|
|
|
|
- istanbul bool // Fork indicator whether we are in the istanbul stage.
|
|
|
|
|
- eip2718 bool // Fork indicator whether we are using EIP-2718 type transactions.
|
|
|
|
|
|
|
+ istanbul bool // 是否处于伊斯坦布尔阶段的标志。
|
|
|
|
|
+ eip2718 bool // 是否使用 EIP-2718 类型的交易的标志。
|
|
|
|
|
|
|
|
- currentState *state.StateDB // Current state in the blockchain head
|
|
|
|
|
- pendingNonces *txNoncer // Pending state tracking virtual nonces
|
|
|
|
|
- currentMaxGas uint64 // Current gas limit for transaction caps
|
|
|
|
|
|
|
+ currentState *state.StateDB // 区块链头中的当前状态
|
|
|
|
|
+ pendingNonces *txNoncer // 跟踪虚拟 nonce 的待处理状态
|
|
|
|
|
+ currentMaxGas uint64 // 当前的 gas 限制,用于交易费用上限
|
|
|
|
|
|
|
|
- locals *accountSet // Set of local transaction to exempt from eviction rules
|
|
|
|
|
- journal *txJournal // Journal of local transaction to back up to disk
|
|
|
|
|
|
|
+ locals *accountSet // 免受淘汰规则限制的本地交易集合
|
|
|
|
|
+ journal *txJournal // 本地交易日志,用于备份到磁盘
|
|
|
|
|
|
|
|
- pending map[common.Address]*txList // All currently processable transactions
|
|
|
|
|
- queue map[common.Address]*txList // Queued but non-processable transactions
|
|
|
|
|
- beats map[common.Address]time.Time // Last heartbeat from each known account
|
|
|
|
|
- all *txLookup // All transactions to allow lookups
|
|
|
|
|
- priced *txPricedList // All transactions sorted by price
|
|
|
|
|
|
|
+ pending map[common.Address]*txList // 当前所有可处理交易
|
|
|
|
|
+ queue map[common.Address]*txList // 排队但无法处理的交易
|
|
|
|
|
+ beats map[common.Address]time.Time // 每个已知账户的最后心跳时间
|
|
|
|
|
+ all *txLookup // 所有交易,用于快速查找
|
|
|
|
|
+ priced *txPricedList // 按价格排序的所有交易
|
|
|
|
|
|
|
|
chainHeadCh chan ChainHeadEvent
|
|
chainHeadCh chan ChainHeadEvent
|
|
|
chainHeadSub event.Subscription
|
|
chainHeadSub event.Subscription
|
|
@@ -261,8 +285,8 @@ type TxPool struct {
|
|
|
reqPromoteCh chan *accountSet
|
|
reqPromoteCh chan *accountSet
|
|
|
queueTxEventCh chan *types.Transaction
|
|
queueTxEventCh chan *types.Transaction
|
|
|
reorgDoneCh chan chan struct{}
|
|
reorgDoneCh chan chan struct{}
|
|
|
- reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop
|
|
|
|
|
- wg sync.WaitGroup // tracks loop, scheduleReorgLoop
|
|
|
|
|
|
|
+ reorgShutdownCh chan struct{} // 请求关闭 scheduleReorgLoop
|
|
|
|
|
+ wg sync.WaitGroup // 追踪循环和 scheduleReorgLoop
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type txpoolResetRequest struct {
|
|
type txpoolResetRequest struct {
|
|
@@ -819,10 +843,9 @@ func (pool *TxPool) AddLocal(tx *types.Transaction) error {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (pool *TxPool) AddLocalFast(tx *types.Transaction) error {
|
|
func (pool *TxPool) AddLocalFast(tx *types.Transaction) error {
|
|
|
- pool.mu.Lock()
|
|
|
|
|
//这里进行tx的添加插播
|
|
//这里进行tx的添加插播
|
|
|
|
|
+ pool.mu.Lock()
|
|
|
pool.all.Add(tx, true)
|
|
pool.all.Add(tx, true)
|
|
|
- pool.priced.Put(tx, true)
|
|
|
|
|
pool.queueTxEvent(tx)
|
|
pool.queueTxEvent(tx)
|
|
|
pool.mu.Unlock()
|
|
pool.mu.Unlock()
|
|
|
return nil
|
|
return nil
|
|
@@ -1039,6 +1062,17 @@ func (pool *TxPool) requestPromoteExecutables(set *accountSet) chan struct{} {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// queueTxEvent enqueues a transaction event to be sent in the next reorg run.
|
|
// queueTxEvent enqueues a transaction event to be sent in the next reorg run.
|
|
|
|
|
+// 函数 queueTxEvent 用于将交易事件加入到下一次重新组织(reorg)运行中。
|
|
|
|
|
+// 在以太坊中,重新组织是指区块链的分叉和重组过程。当发生区块链重组时,之前加入交易池但尚未执行的交易可能会发生状态变化。
|
|
|
|
|
+// 因此,在重新组织过程中,需要重新处理这些交易。
|
|
|
|
|
+//
|
|
|
|
|
+// 具体而言,queueTxEvent 函数将交易对象 tx 加入到交易事件队列 pool.queueTxEventCh 中。
|
|
|
|
|
+// 该队列用于存储待处理的交易事件。当交易池进行重新组织时,会处理这些交易事件以确保交易状态的一致性。
|
|
|
|
|
+//
|
|
|
|
|
+// 在函数的实现中,使用了一个非阻塞的 select 语句,尝试将交易事件发送到 pool.queueTxEventCh。
|
|
|
|
|
+// 如果成功发送,则交易事件被加入到队列中。如果在发送时发现 pool.reorgShutdownCh 通道已关闭(即重新组织过程被关闭),则会立即退出函数。
|
|
|
|
|
+//
|
|
|
|
|
+// 总之,queueTxEvent 函数用于将待处理的交易事件加入到队列中,以便在重新组织过程中进行处理。这有助于保持交易池中交易状态的一致性。
|
|
|
func (pool *TxPool) queueTxEvent(tx *types.Transaction) {
|
|
func (pool *TxPool) queueTxEvent(tx *types.Transaction) {
|
|
|
select {
|
|
select {
|
|
|
case pool.queueTxEventCh <- tx:
|
|
case pool.queueTxEventCh <- tx:
|
|
@@ -1627,6 +1661,13 @@ func (as *accountSet) merge(other *accountSet) {
|
|
|
//
|
|
//
|
|
|
// This lookup set combines the notion of "local transactions", which is useful
|
|
// This lookup set combines the notion of "local transactions", which is useful
|
|
|
// to build upper-level structure.
|
|
// to build upper-level structure.
|
|
|
|
|
+
|
|
|
|
|
+// txLookup 被 TxPool 内部用于在不使用互斥锁竞争的情况下跟踪交易并允许查找。
|
|
|
|
|
+//
|
|
|
|
|
+// 注意,尽管这个类型在并发访问方面受到适当的保护,但它**不是**一种应该被修改甚至在事务池之外暴露的类型,因为它的内部状态与池的内部机制紧密耦合。
|
|
|
|
|
+// 这个类型的唯一目的是允许在不必获取广泛范围的 TxPool.mu 互斥锁的情况下,在 TxPool.Get 中对池进行超出边界的查看。
|
|
|
|
|
+//
|
|
|
|
|
+// 这个查找集合结合了“本地交易”的概念,对于构建上层结构非常有用。
|
|
|
type txLookup struct {
|
|
type txLookup struct {
|
|
|
slots int
|
|
slots int
|
|
|
lock sync.RWMutex
|
|
lock sync.RWMutex
|
|
@@ -1725,6 +1766,17 @@ func (t *txLookup) Slots() int {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Add adds a transaction to the lookup.
|
|
// Add adds a transaction to the lookup.
|
|
|
|
|
+// 函数 `Add` 用于向查找表(txLookup)中添加一个交易。
|
|
|
|
|
+//
|
|
|
|
|
+// 具体而言,该函数执行以下操作:
|
|
|
|
|
+// 1. 获取查找表的互斥锁(t.lock)以确保并发安全。
|
|
|
|
|
+// 2. 根据交易的类型(local 或 remote),将交易添加到相应的映射表中。
|
|
|
|
|
+// - 如果交易被标记为 local,则将其添加到 `t.locals` 映射表中,使用交易的哈希(tx.Hash())作为键,交易对象(tx)作为值。
|
|
|
|
|
+// - 如果交易被标记为 remote,则将其添加到 `t.remotes` 映射表中,使用交易的哈希作为键,交易对象作为值。
|
|
|
|
|
+// 3. 更新查找表的插槽计数(t.slots),增加交易的插槽数(numSlots(tx))。
|
|
|
|
|
+// 4. 更新插槽计数的度量指标(slotsGauge)。
|
|
|
|
|
+//
|
|
|
|
|
+// 通过这些操作,函数将交易添加到查找表中,并相应地更新计数和度量指标。查找表可用于高效地查找和管理交易,并根据交易类型进行分类。
|
|
|
func (t *txLookup) Add(tx *types.Transaction, local bool) {
|
|
func (t *txLookup) Add(tx *types.Transaction, local bool) {
|
|
|
t.lock.Lock()
|
|
t.lock.Lock()
|
|
|
defer t.lock.Unlock()
|
|
defer t.lock.Unlock()
|