mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
revert the changes in blobTxMeta
This commit is contained in:
parent
98af70fdb7
commit
e9da3f2369
5 changed files with 208 additions and 208 deletions
|
|
@ -90,20 +90,20 @@ const (
|
||||||
// bare minimum needed fields to keep the size down (and thus number of entries
|
// bare minimum needed fields to keep the size down (and thus number of entries
|
||||||
// larger with the same memory consumption).
|
// larger with the same memory consumption).
|
||||||
type blobTxMeta struct {
|
type blobTxMeta struct {
|
||||||
TxHash common.Hash // Transaction hash to maintain the lookup table
|
hash common.Hash // Transaction hash to maintain the lookup table
|
||||||
VHashes []common.Hash // Blob versioned hashes to maintain the lookup table
|
vhashes []common.Hash // Blob versioned hashes to maintain the lookup table
|
||||||
|
|
||||||
Id uint64 // Storage ID in the pool's persistent store
|
id uint64 // Storage ID in the pool's persistent store
|
||||||
StorageSize uint32 // Byte size in the pool's persistent store
|
storageSize uint32 // Byte size in the pool's persistent store
|
||||||
Size uint64 // RLP-encoded size of transaction including the attached blob
|
size uint64 // RLP-encoded size of transaction including the attached blob
|
||||||
|
|
||||||
Nonce uint64 // Needed to prioritize inclusion order within an account
|
nonce uint64 // Needed to prioritize inclusion order within an account
|
||||||
CostCap *uint256.Int // Needed to validate cumulative balance sufficiency
|
costCap *uint256.Int // Needed to validate cumulative balance sufficiency
|
||||||
ExecTipCap *uint256.Int // Needed to prioritize inclusion order across accounts and validate replacement price bump
|
execTipCap *uint256.Int // Needed to prioritize inclusion order across accounts and validate replacement price bump
|
||||||
ExecFeeCap *uint256.Int // Needed to validate replacement price bump
|
execFeeCap *uint256.Int // Needed to validate replacement price bump
|
||||||
BlobFeeCap *uint256.Int // Needed to validate replacement price bump
|
blobFeeCap *uint256.Int // Needed to validate replacement price bump
|
||||||
ExecGas uint64 // Needed to check inclusion validity before reading the blob
|
execGas uint64 // Needed to check inclusion validity before reading the blob
|
||||||
BlobGas uint64 // Needed to check inclusion validity before reading the blob
|
blobGas uint64 // Needed to check inclusion validity before reading the blob
|
||||||
|
|
||||||
basefeeJumps float64 // Absolute number of 1559 fee adjustments needed to reach the tx's fee cap
|
basefeeJumps float64 // Absolute number of 1559 fee adjustments needed to reach the tx's fee cap
|
||||||
blobfeeJumps float64 // Absolute number of 4844 fee adjustments needed to reach the tx's blob fee cap
|
blobfeeJumps float64 // Absolute number of 4844 fee adjustments needed to reach the tx's blob fee cap
|
||||||
|
|
@ -117,21 +117,21 @@ type blobTxMeta struct {
|
||||||
// and assembles a helper struct to track in memory.
|
// and assembles a helper struct to track in memory.
|
||||||
func newBlobTxMeta(id uint64, size uint64, storageSize uint32, tx *types.Transaction) *blobTxMeta {
|
func newBlobTxMeta(id uint64, size uint64, storageSize uint32, tx *types.Transaction) *blobTxMeta {
|
||||||
meta := &blobTxMeta{
|
meta := &blobTxMeta{
|
||||||
TxHash: tx.Hash(),
|
hash: tx.Hash(),
|
||||||
VHashes: tx.BlobHashes(),
|
vhashes: tx.BlobHashes(),
|
||||||
Id: id,
|
id: id,
|
||||||
StorageSize: storageSize,
|
storageSize: storageSize,
|
||||||
Size: size,
|
size: size,
|
||||||
Nonce: tx.Nonce(),
|
nonce: tx.Nonce(),
|
||||||
CostCap: uint256.MustFromBig(tx.Cost()),
|
costCap: uint256.MustFromBig(tx.Cost()),
|
||||||
ExecTipCap: uint256.MustFromBig(tx.GasTipCap()),
|
execTipCap: uint256.MustFromBig(tx.GasTipCap()),
|
||||||
ExecFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
|
execFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
|
||||||
BlobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()),
|
blobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()),
|
||||||
ExecGas: tx.Gas(),
|
execGas: tx.Gas(),
|
||||||
BlobGas: tx.BlobGas(),
|
blobGas: tx.BlobGas(),
|
||||||
}
|
}
|
||||||
meta.basefeeJumps = dynamicFeeJumps(meta.ExecFeeCap)
|
meta.basefeeJumps = dynamicFeeJumps(meta.execFeeCap)
|
||||||
meta.blobfeeJumps = dynamicFeeJumps(meta.BlobFeeCap)
|
meta.blobfeeJumps = dynamicFeeJumps(meta.blobFeeCap)
|
||||||
|
|
||||||
return meta
|
return meta
|
||||||
}
|
}
|
||||||
|
|
@ -486,7 +486,7 @@ func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := newBlobTxMeta(id, tx.Size(), size, tx)
|
meta := newBlobTxMeta(id, tx.Size(), size, tx)
|
||||||
if p.lookup.exists(meta.TxHash) {
|
if p.lookup.exists(meta.hash) {
|
||||||
// This path is only possible after a crash, where deleted items are not
|
// This path is only possible after a crash, where deleted items are not
|
||||||
// removed via the normal shutdown-startup procedure and thus may get
|
// removed via the normal shutdown-startup procedure and thus may get
|
||||||
// partially resurrected.
|
// partially resurrected.
|
||||||
|
|
@ -509,10 +509,10 @@ func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error {
|
||||||
p.spent[sender] = new(uint256.Int)
|
p.spent[sender] = new(uint256.Int)
|
||||||
}
|
}
|
||||||
p.index[sender] = append(p.index[sender], meta)
|
p.index[sender] = append(p.index[sender], meta)
|
||||||
p.spent[sender] = new(uint256.Int).Add(p.spent[sender], meta.CostCap)
|
p.spent[sender] = new(uint256.Int).Add(p.spent[sender], meta.costCap)
|
||||||
|
|
||||||
p.lookup.track(meta)
|
p.lookup.track(meta)
|
||||||
p.stored += uint64(meta.StorageSize)
|
p.stored += uint64(meta.storageSize)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -525,15 +525,15 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sort.Slice(txs, func(i, j int) bool {
|
sort.Slice(txs, func(i, j int) bool {
|
||||||
return txs[i].Nonce < txs[j].Nonce
|
return txs[i].nonce < txs[j].nonce
|
||||||
})
|
})
|
||||||
// If there is a gap between the chain state and the blob pool, drop
|
// If there is a gap between the chain state and the blob pool, drop
|
||||||
// all the transactions as they are non-executable. Similarly, if the
|
// all the transactions as they are non-executable. Similarly, if the
|
||||||
// entire tx range was included, drop all.
|
// entire tx range was included, drop all.
|
||||||
var (
|
var (
|
||||||
next = p.state.GetNonce(addr)
|
next = p.state.GetNonce(addr)
|
||||||
gapped = txs[0].Nonce > next
|
gapped = txs[0].nonce > next
|
||||||
filled = txs[len(txs)-1].Nonce < next
|
filled = txs[len(txs)-1].nonce < next
|
||||||
)
|
)
|
||||||
if gapped || filled {
|
if gapped || filled {
|
||||||
var (
|
var (
|
||||||
|
|
@ -541,13 +541,13 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
nonces []uint64
|
nonces []uint64
|
||||||
)
|
)
|
||||||
for i := 0; i < len(txs); i++ {
|
for i := 0; i < len(txs); i++ {
|
||||||
ids = append(ids, txs[i].Id)
|
ids = append(ids, txs[i].id)
|
||||||
nonces = append(nonces, txs[i].Nonce)
|
nonces = append(nonces, txs[i].nonce)
|
||||||
|
|
||||||
p.stored -= uint64(txs[i].StorageSize)
|
p.stored -= uint64(txs[i].storageSize)
|
||||||
p.lookup.untrack(txs[i])
|
p.lookup.untrack(txs[i])
|
||||||
|
|
||||||
// Included transactions blobs need to be recorded in the limbo
|
// Included transactions blobs need to be moved to the limbo
|
||||||
if filled && inclusions != nil {
|
if filled && inclusions != nil {
|
||||||
p.offload(addr, txs[i], inclusions)
|
p.offload(addr, txs[i], inclusions)
|
||||||
}
|
}
|
||||||
|
|
@ -579,20 +579,20 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
}
|
}
|
||||||
// If there is overlap between the chain state and the blob pool, drop
|
// If there is overlap between the chain state and the blob pool, drop
|
||||||
// anything below the current state
|
// anything below the current state
|
||||||
if txs[0].Nonce < next {
|
if txs[0].nonce < next {
|
||||||
var (
|
var (
|
||||||
ids []uint64
|
ids []uint64
|
||||||
nonces []uint64
|
nonces []uint64
|
||||||
)
|
)
|
||||||
for len(txs) > 0 && txs[0].Nonce < next {
|
for len(txs) > 0 && txs[0].nonce < next {
|
||||||
ids = append(ids, txs[0].Id)
|
ids = append(ids, txs[0].id)
|
||||||
nonces = append(nonces, txs[0].Nonce)
|
nonces = append(nonces, txs[0].nonce)
|
||||||
|
|
||||||
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[0].CostCap)
|
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[0].costCap)
|
||||||
p.stored -= uint64(txs[0].StorageSize)
|
p.stored -= uint64(txs[0].storageSize)
|
||||||
p.lookup.untrack(txs[0])
|
p.lookup.untrack(txs[0])
|
||||||
|
|
||||||
// Included transactions blobs need to be recorded in the limbo.
|
// Included transactions blobs need to be moved to the limbo
|
||||||
if inclusions != nil {
|
if inclusions != nil {
|
||||||
p.offload(addr, txs[0], inclusions)
|
p.offload(addr, txs[0], inclusions)
|
||||||
}
|
}
|
||||||
|
|
@ -613,17 +613,17 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
}
|
}
|
||||||
// Iterate over the transactions to initialize their eviction thresholds
|
// Iterate over the transactions to initialize their eviction thresholds
|
||||||
// and to detect any nonce gaps
|
// and to detect any nonce gaps
|
||||||
txs[0].evictionExecTip = txs[0].ExecTipCap
|
txs[0].evictionExecTip = txs[0].execTipCap
|
||||||
txs[0].evictionExecFeeJumps = txs[0].basefeeJumps
|
txs[0].evictionExecFeeJumps = txs[0].basefeeJumps
|
||||||
txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps
|
txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps
|
||||||
|
|
||||||
for i := 1; i < len(txs); i++ {
|
for i := 1; i < len(txs); i++ {
|
||||||
// If there's no nonce gap, initialize the eviction thresholds as the
|
// If there's no nonce gap, initialize the eviction thresholds as the
|
||||||
// minimum between the cumulative thresholds and the current tx fees
|
// minimum between the cumulative thresholds and the current tx fees
|
||||||
if txs[i].Nonce == txs[i-1].Nonce+1 {
|
if txs[i].nonce == txs[i-1].nonce+1 {
|
||||||
txs[i].evictionExecTip = txs[i-1].evictionExecTip
|
txs[i].evictionExecTip = txs[i-1].evictionExecTip
|
||||||
if txs[i].evictionExecTip.Cmp(txs[i].ExecTipCap) > 0 {
|
if txs[i].evictionExecTip.Cmp(txs[i].execTipCap) > 0 {
|
||||||
txs[i].evictionExecTip = txs[i].ExecTipCap
|
txs[i].evictionExecTip = txs[i].execTipCap
|
||||||
}
|
}
|
||||||
txs[i].evictionExecFeeJumps = txs[i-1].evictionExecFeeJumps
|
txs[i].evictionExecFeeJumps = txs[i-1].evictionExecFeeJumps
|
||||||
if txs[i].evictionExecFeeJumps > txs[i].basefeeJumps {
|
if txs[i].evictionExecFeeJumps > txs[i].basefeeJumps {
|
||||||
|
|
@ -641,14 +641,14 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
// Also, Billy behind the blobpool does not journal deletes. A process
|
// Also, Billy behind the blobpool does not journal deletes. A process
|
||||||
// crash would result in previously deleted entities being resurrected.
|
// crash would result in previously deleted entities being resurrected.
|
||||||
// That could potentially cause a duplicate nonce to appear.
|
// That could potentially cause a duplicate nonce to appear.
|
||||||
if txs[i].Nonce == txs[i-1].Nonce {
|
if txs[i].nonce == txs[i-1].nonce {
|
||||||
id, _ := p.lookup.storeidOfTx(txs[i].TxHash)
|
id, _ := p.lookup.storeidOfTx(txs[i].hash)
|
||||||
|
|
||||||
log.Error("Dropping repeat Nonce blob transaction", "from", addr, "nonce", txs[i].Nonce, "id", id)
|
log.Error("Dropping repeat nonce blob transaction", "from", addr, "nonce", txs[i].nonce, "id", id)
|
||||||
dropRepeatedMeter.Mark(1)
|
dropRepeatedMeter.Mark(1)
|
||||||
|
|
||||||
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[i].CostCap)
|
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[i].costCap)
|
||||||
p.stored -= uint64(txs[i].StorageSize)
|
p.stored -= uint64(txs[i].storageSize)
|
||||||
p.lookup.untrack(txs[i])
|
p.lookup.untrack(txs[i])
|
||||||
|
|
||||||
if err := p.store.Delete(id); err != nil {
|
if err := p.store.Delete(id); err != nil {
|
||||||
|
|
@ -666,16 +666,16 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
nonces []uint64
|
nonces []uint64
|
||||||
)
|
)
|
||||||
for j := i; j < len(txs); j++ {
|
for j := i; j < len(txs); j++ {
|
||||||
ids = append(ids, txs[j].Id)
|
ids = append(ids, txs[j].id)
|
||||||
nonces = append(nonces, txs[j].Nonce)
|
nonces = append(nonces, txs[j].nonce)
|
||||||
|
|
||||||
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[j].CostCap)
|
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[j].costCap)
|
||||||
p.stored -= uint64(txs[j].StorageSize)
|
p.stored -= uint64(txs[j].storageSize)
|
||||||
p.lookup.untrack(txs[j])
|
p.lookup.untrack(txs[j])
|
||||||
}
|
}
|
||||||
txs = txs[:i]
|
txs = txs[:i]
|
||||||
|
|
||||||
log.Error("Dropping gapped blob transactions", "from", addr, "missing", txs[i-1].Nonce+1, "drop", nonces, "ids", ids)
|
log.Error("Dropping gapped blob transactions", "from", addr, "missing", txs[i-1].nonce+1, "drop", nonces, "ids", ids)
|
||||||
dropGappedMeter.Mark(int64(len(ids)))
|
dropGappedMeter.Mark(int64(len(ids)))
|
||||||
|
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
|
|
@ -704,11 +704,11 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
txs[len(txs)-1] = nil
|
txs[len(txs)-1] = nil
|
||||||
txs = txs[:len(txs)-1]
|
txs = txs[:len(txs)-1]
|
||||||
|
|
||||||
ids = append(ids, last.Id)
|
ids = append(ids, last.id)
|
||||||
nonces = append(nonces, last.Nonce)
|
nonces = append(nonces, last.nonce)
|
||||||
|
|
||||||
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], last.CostCap)
|
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], last.costCap)
|
||||||
p.stored -= uint64(last.StorageSize)
|
p.stored -= uint64(last.storageSize)
|
||||||
p.lookup.untrack(last)
|
p.lookup.untrack(last)
|
||||||
}
|
}
|
||||||
if len(txs) == 0 {
|
if len(txs) == 0 {
|
||||||
|
|
@ -744,11 +744,11 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
txs[len(txs)-1] = nil
|
txs[len(txs)-1] = nil
|
||||||
txs = txs[:len(txs)-1]
|
txs = txs[:len(txs)-1]
|
||||||
|
|
||||||
ids = append(ids, last.Id)
|
ids = append(ids, last.id)
|
||||||
nonces = append(nonces, last.Nonce)
|
nonces = append(nonces, last.nonce)
|
||||||
|
|
||||||
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], last.CostCap)
|
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], last.costCap)
|
||||||
p.stored -= uint64(last.StorageSize)
|
p.stored -= uint64(last.storageSize)
|
||||||
p.lookup.untrack(last)
|
p.lookup.untrack(last)
|
||||||
}
|
}
|
||||||
p.index[addr] = txs
|
p.index[addr] = txs
|
||||||
|
|
@ -777,9 +777,9 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
|
||||||
// issues, others caused by signers mining MEV stuff or swapping transactions. In
|
// issues, others caused by signers mining MEV stuff or swapping transactions. In
|
||||||
// all cases, the pool needs to continue operating.
|
// all cases, the pool needs to continue operating.
|
||||||
func (p *BlobPool) offload(addr common.Address, blobTxMeta *blobTxMeta, inclusions map[common.Hash]uint64) {
|
func (p *BlobPool) offload(addr common.Address, blobTxMeta *blobTxMeta, inclusions map[common.Hash]uint64) {
|
||||||
block, ok := inclusions[blobTxMeta.TxHash]
|
block, ok := inclusions[blobTxMeta.hash]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Warn("Blob transaction swapped out by signer", "from", addr, "nonce", blobTxMeta.Nonce, "id", blobTxMeta.Id)
|
log.Warn("Blob transaction swapped out by signer", "from", addr, "nonce", blobTxMeta.nonce, "id", blobTxMeta.id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := p.limbo.push(blobTxMeta, block); err != nil {
|
if err := p.limbo.push(blobTxMeta, block); err != nil {
|
||||||
|
|
@ -995,18 +995,18 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
|
||||||
}
|
}
|
||||||
if _, ok := p.index[addr]; !ok {
|
if _, ok := p.index[addr]; !ok {
|
||||||
if err := p.reserver.Hold(addr); err != nil {
|
if err := p.reserver.Hold(addr); err != nil {
|
||||||
log.Warn("Failed to reserve account for blob pool", "tx", meta.TxHash, "from", addr, "err", err)
|
log.Warn("Failed to reserve account for blob pool", "tx", meta.hash, "from", addr, "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.index[addr] = []*blobTxMeta{meta}
|
p.index[addr] = []*blobTxMeta{meta}
|
||||||
p.spent[addr] = meta.CostCap
|
p.spent[addr] = meta.costCap
|
||||||
p.evict.Push(addr)
|
p.evict.Push(addr)
|
||||||
} else {
|
} else {
|
||||||
p.index[addr] = append(p.index[addr], meta)
|
p.index[addr] = append(p.index[addr], meta)
|
||||||
p.spent[addr] = new(uint256.Int).Add(p.spent[addr], meta.CostCap)
|
p.spent[addr] = new(uint256.Int).Add(p.spent[addr], meta.costCap)
|
||||||
}
|
}
|
||||||
p.lookup.track(meta)
|
p.lookup.track(meta)
|
||||||
p.stored += uint64(meta.StorageSize)
|
p.stored += uint64(meta.storageSize)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1024,24 +1024,24 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
|
||||||
if old == nil || p.gasTip.Cmp(old) > 0 {
|
if old == nil || p.gasTip.Cmp(old) > 0 {
|
||||||
for addr, txs := range p.index {
|
for addr, txs := range p.index {
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
if tx.ExecTipCap.Cmp(p.gasTip) < 0 {
|
if tx.execTipCap.Cmp(p.gasTip) < 0 {
|
||||||
// Drop the offending transaction
|
// Drop the offending transaction
|
||||||
var (
|
var (
|
||||||
ids = []uint64{tx.Id}
|
ids = []uint64{tx.id}
|
||||||
nonces = []uint64{tx.Nonce}
|
nonces = []uint64{tx.nonce}
|
||||||
)
|
)
|
||||||
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[i].CostCap)
|
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[i].costCap)
|
||||||
p.stored -= uint64(tx.StorageSize)
|
p.stored -= uint64(tx.storageSize)
|
||||||
p.lookup.untrack(tx)
|
p.lookup.untrack(tx)
|
||||||
txs[i] = nil
|
txs[i] = nil
|
||||||
|
|
||||||
// Drop everything afterwards, no gaps allowed
|
// Drop everything afterwards, no gaps allowed
|
||||||
for j, tx := range txs[i+1:] {
|
for j, tx := range txs[i+1:] {
|
||||||
ids = append(ids, tx.Id)
|
ids = append(ids, tx.id)
|
||||||
nonces = append(nonces, tx.Nonce)
|
nonces = append(nonces, tx.nonce)
|
||||||
|
|
||||||
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], tx.CostCap)
|
p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], tx.costCap)
|
||||||
p.stored -= uint64(tx.StorageSize)
|
p.stored -= uint64(tx.storageSize)
|
||||||
p.lookup.untrack(tx)
|
p.lookup.untrack(tx)
|
||||||
txs[i+1+j] = nil
|
txs[i+1+j] = nil
|
||||||
}
|
}
|
||||||
|
|
@ -1057,7 +1057,7 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
|
||||||
p.reserver.Release(addr)
|
p.reserver.Release(addr)
|
||||||
}
|
}
|
||||||
// Clear out the transactions from the data store
|
// Clear out the transactions from the data store
|
||||||
log.Warn("Dropping underpriced blob transaction", "from", addr, "rejected", tx.Nonce, "tip", tx.ExecTipCap, "want", tip, "drop", nonces, "ids", ids)
|
log.Warn("Dropping underpriced blob transaction", "from", addr, "rejected", tx.nonce, "tip", tx.execTipCap, "want", tip, "drop", nonces, "ids", ids)
|
||||||
dropUnderpricedMeter.Mark(int64(len(ids)))
|
dropUnderpricedMeter.Mark(int64(len(ids)))
|
||||||
|
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
|
|
@ -1117,7 +1117,7 @@ func (p *BlobPool) checkDelegationLimit(tx *types.Transaction) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If account already has a pending transaction, allow replacement only.
|
// If account already has a pending transaction, allow replacement only.
|
||||||
if len(pending) == 1 && pending[0].Nonce == tx.Nonce() {
|
if len(pending) == 1 && pending[0].nonce == tx.Nonce() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return txpool.ErrInflightTxLimitReached
|
return txpool.ErrInflightTxLimitReached
|
||||||
|
|
@ -1155,7 +1155,7 @@ func (p *BlobPool) validateTx(tx *types.Transaction) error {
|
||||||
ExistingCost: func(addr common.Address, nonce uint64) *big.Int {
|
ExistingCost: func(addr common.Address, nonce uint64) *big.Int {
|
||||||
next := p.state.GetNonce(addr)
|
next := p.state.GetNonce(addr)
|
||||||
if uint64(len(p.index[addr])) > nonce-next {
|
if uint64(len(p.index[addr])) > nonce-next {
|
||||||
return p.index[addr][int(nonce-next)].CostCap.ToBig()
|
return p.index[addr][int(nonce-next)].costCap.ToBig()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
@ -1175,33 +1175,33 @@ func (p *BlobPool) validateTx(tx *types.Transaction) error {
|
||||||
if uint64(len(p.index[from])) > tx.Nonce()-next {
|
if uint64(len(p.index[from])) > tx.Nonce()-next {
|
||||||
prev := p.index[from][int(tx.Nonce()-next)]
|
prev := p.index[from][int(tx.Nonce()-next)]
|
||||||
// Ensure the transaction is different than the one tracked locally
|
// Ensure the transaction is different than the one tracked locally
|
||||||
if prev.TxHash == tx.Hash() {
|
if prev.hash == tx.Hash() {
|
||||||
return txpool.ErrAlreadyKnown
|
return txpool.ErrAlreadyKnown
|
||||||
}
|
}
|
||||||
// Account can support the replacement, but the price bump must also be met
|
// Account can support the replacement, but the price bump must also be met
|
||||||
switch {
|
switch {
|
||||||
case tx.GasFeeCapIntCmp(prev.ExecFeeCap.ToBig()) <= 0:
|
case tx.GasFeeCapIntCmp(prev.execFeeCap.ToBig()) <= 0:
|
||||||
return fmt.Errorf("%w: new tx gas fee cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.GasFeeCap(), prev.ExecFeeCap)
|
return fmt.Errorf("%w: new tx gas fee cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.GasFeeCap(), prev.execFeeCap)
|
||||||
case tx.GasTipCapIntCmp(prev.ExecTipCap.ToBig()) <= 0:
|
case tx.GasTipCapIntCmp(prev.execTipCap.ToBig()) <= 0:
|
||||||
return fmt.Errorf("%w: new tx gas tip cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.GasTipCap(), prev.ExecTipCap)
|
return fmt.Errorf("%w: new tx gas tip cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.GasTipCap(), prev.execTipCap)
|
||||||
case tx.BlobGasFeeCapIntCmp(prev.BlobFeeCap.ToBig()) <= 0:
|
case tx.BlobGasFeeCapIntCmp(prev.blobFeeCap.ToBig()) <= 0:
|
||||||
return fmt.Errorf("%w: new tx blob gas fee cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.BlobGasFeeCap(), prev.BlobFeeCap)
|
return fmt.Errorf("%w: new tx blob gas fee cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.BlobGasFeeCap(), prev.blobFeeCap)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
multiplier = uint256.NewInt(100 + p.config.PriceBump)
|
multiplier = uint256.NewInt(100 + p.config.PriceBump)
|
||||||
onehundred = uint256.NewInt(100)
|
onehundred = uint256.NewInt(100)
|
||||||
|
|
||||||
minGasFeeCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.ExecFeeCap), onehundred)
|
minGasFeeCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.execFeeCap), onehundred)
|
||||||
minGasTipCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.ExecTipCap), onehundred)
|
minGasTipCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.execTipCap), onehundred)
|
||||||
minBlobGasFeeCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.BlobFeeCap), onehundred)
|
minBlobGasFeeCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.blobFeeCap), onehundred)
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
case tx.GasFeeCapIntCmp(minGasFeeCap.ToBig()) < 0:
|
case tx.GasFeeCapIntCmp(minGasFeeCap.ToBig()) < 0:
|
||||||
return fmt.Errorf("%w: new tx gas fee cap %v < %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.GasFeeCap(), prev.ExecFeeCap, p.config.PriceBump)
|
return fmt.Errorf("%w: new tx gas fee cap %v < %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.GasFeeCap(), prev.execFeeCap, p.config.PriceBump)
|
||||||
case tx.GasTipCapIntCmp(minGasTipCap.ToBig()) < 0:
|
case tx.GasTipCapIntCmp(minGasTipCap.ToBig()) < 0:
|
||||||
return fmt.Errorf("%w: new tx gas tip cap %v < %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.GasTipCap(), prev.ExecTipCap, p.config.PriceBump)
|
return fmt.Errorf("%w: new tx gas tip cap %v < %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.GasTipCap(), prev.execTipCap, p.config.PriceBump)
|
||||||
case tx.BlobGasFeeCapIntCmp(minBlobGasFeeCap.ToBig()) < 0:
|
case tx.BlobGasFeeCapIntCmp(minBlobGasFeeCap.ToBig()) < 0:
|
||||||
return fmt.Errorf("%w: new tx blob gas fee cap %v < %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.BlobGasFeeCap(), prev.BlobFeeCap, p.config.PriceBump)
|
return fmt.Errorf("%w: new tx blob gas fee cap %v < %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.BlobGasFeeCap(), prev.blobFeeCap, p.config.PriceBump)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -1422,7 +1422,7 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
|
||||||
|
|
||||||
// Ensure the transaction is valid from all perspectives
|
// Ensure the transaction is valid from all perspectives
|
||||||
if err := p.validateTx(tx); err != nil {
|
if err := p.validateTx(tx); err != nil {
|
||||||
log.Trace("Transaction validation failed", "TxHash", tx.Hash(), "err", err)
|
log.Trace("Transaction validation failed", "hash", tx.Hash(), "err", err)
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, txpool.ErrUnderpriced):
|
case errors.Is(err, txpool.ErrUnderpriced):
|
||||||
addUnderpricedMeter.Mark(1)
|
addUnderpricedMeter.Mark(1)
|
||||||
|
|
@ -1491,18 +1491,18 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
|
||||||
dropReplacedMeter.Mark(1)
|
dropReplacedMeter.Mark(1)
|
||||||
|
|
||||||
prev := p.index[from][offset]
|
prev := p.index[from][offset]
|
||||||
if err := p.store.Delete(prev.Id); err != nil {
|
if err := p.store.Delete(prev.id); err != nil {
|
||||||
// Shitty situation, but try to recover gracefully instead of going boom
|
// Shitty situation, but try to recover gracefully instead of going boom
|
||||||
log.Error("Failed to delete replaced transaction", "id", prev.Id, "err", err)
|
log.Error("Failed to delete replaced transaction", "id", prev.id, "err", err)
|
||||||
}
|
}
|
||||||
// Update the transaction index
|
// Update the transaction index
|
||||||
p.index[from][offset] = meta
|
p.index[from][offset] = meta
|
||||||
p.spent[from] = new(uint256.Int).Sub(p.spent[from], prev.CostCap)
|
p.spent[from] = new(uint256.Int).Sub(p.spent[from], prev.costCap)
|
||||||
p.spent[from] = new(uint256.Int).Add(p.spent[from], meta.CostCap)
|
p.spent[from] = new(uint256.Int).Add(p.spent[from], meta.costCap)
|
||||||
|
|
||||||
p.lookup.untrack(prev)
|
p.lookup.untrack(prev)
|
||||||
p.lookup.track(meta)
|
p.lookup.track(meta)
|
||||||
p.stored += uint64(meta.StorageSize) - uint64(prev.StorageSize)
|
p.stored += uint64(meta.storageSize) - uint64(prev.storageSize)
|
||||||
} else {
|
} else {
|
||||||
// Transaction extends previously scheduled ones
|
// Transaction extends previously scheduled ones
|
||||||
p.index[from] = append(p.index[from], meta)
|
p.index[from] = append(p.index[from], meta)
|
||||||
|
|
@ -1510,9 +1510,9 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
|
||||||
p.spent[from] = new(uint256.Int)
|
p.spent[from] = new(uint256.Int)
|
||||||
newacc = true
|
newacc = true
|
||||||
}
|
}
|
||||||
p.spent[from] = new(uint256.Int).Add(p.spent[from], meta.CostCap)
|
p.spent[from] = new(uint256.Int).Add(p.spent[from], meta.costCap)
|
||||||
p.lookup.track(meta)
|
p.lookup.track(meta)
|
||||||
p.stored += uint64(meta.StorageSize)
|
p.stored += uint64(meta.storageSize)
|
||||||
}
|
}
|
||||||
// Recompute the rolling eviction fields. In case of a replacement, this will
|
// Recompute the rolling eviction fields. In case of a replacement, this will
|
||||||
// recompute all subsequent fields. In case of an append, this will only do
|
// recompute all subsequent fields. In case of an append, this will only do
|
||||||
|
|
@ -1522,7 +1522,7 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
|
||||||
for i := offset; i < len(txs); i++ {
|
for i := offset; i < len(txs); i++ {
|
||||||
// The first transaction will always use itself
|
// The first transaction will always use itself
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
txs[0].evictionExecTip = txs[0].ExecTipCap
|
txs[0].evictionExecTip = txs[0].execTipCap
|
||||||
txs[0].evictionExecFeeJumps = txs[0].basefeeJumps
|
txs[0].evictionExecFeeJumps = txs[0].basefeeJumps
|
||||||
txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps
|
txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps
|
||||||
|
|
||||||
|
|
@ -1530,8 +1530,8 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
|
||||||
}
|
}
|
||||||
// Subsequent transactions will use a rolling calculation
|
// Subsequent transactions will use a rolling calculation
|
||||||
txs[i].evictionExecTip = txs[i-1].evictionExecTip
|
txs[i].evictionExecTip = txs[i-1].evictionExecTip
|
||||||
if txs[i].evictionExecTip.Cmp(txs[i].ExecTipCap) > 0 {
|
if txs[i].evictionExecTip.Cmp(txs[i].execTipCap) > 0 {
|
||||||
txs[i].evictionExecTip = txs[i].ExecTipCap
|
txs[i].evictionExecTip = txs[i].execTipCap
|
||||||
}
|
}
|
||||||
txs[i].evictionExecFeeJumps = txs[i-1].evictionExecFeeJumps
|
txs[i].evictionExecFeeJumps = txs[i-1].evictionExecFeeJumps
|
||||||
if txs[i].evictionExecFeeJumps > txs[i].basefeeJumps {
|
if txs[i].evictionExecFeeJumps > txs[i].basefeeJumps {
|
||||||
|
|
@ -1597,9 +1597,9 @@ func (p *BlobPool) drop() {
|
||||||
txs = txs[:len(txs)-1]
|
txs = txs[:len(txs)-1]
|
||||||
|
|
||||||
p.index[from] = txs
|
p.index[from] = txs
|
||||||
p.spent[from] = new(uint256.Int).Sub(p.spent[from], drop.CostCap)
|
p.spent[from] = new(uint256.Int).Sub(p.spent[from], drop.costCap)
|
||||||
}
|
}
|
||||||
p.stored -= uint64(drop.StorageSize)
|
p.stored -= uint64(drop.storageSize)
|
||||||
p.lookup.untrack(drop)
|
p.lookup.untrack(drop)
|
||||||
|
|
||||||
// Remove the transaction from the pool's eviction heap:
|
// Remove the transaction from the pool's eviction heap:
|
||||||
|
|
@ -1618,11 +1618,11 @@ func (p *BlobPool) drop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove the transaction from the data store
|
// Remove the transaction from the data store
|
||||||
log.Debug("Evicting overflown blob transaction", "from", from, "evicted", drop.Nonce, "id", drop.Id)
|
log.Debug("Evicting overflown blob transaction", "from", from, "evicted", drop.nonce, "id", drop.id)
|
||||||
dropOverflownMeter.Mark(1)
|
dropOverflownMeter.Mark(1)
|
||||||
|
|
||||||
if err := p.store.Delete(drop.Id); err != nil {
|
if err := p.store.Delete(drop.id); err != nil {
|
||||||
log.Error("Failed to drop evicted transaction", "id", drop.Id, "err", err)
|
log.Error("Failed to drop evicted transaction", "id", drop.id, "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1657,36 +1657,36 @@ func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*tx
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
// If transaction filtering was requested, discard badly priced ones
|
// If transaction filtering was requested, discard badly priced ones
|
||||||
if filter.MinTip != nil && filter.BaseFee != nil {
|
if filter.MinTip != nil && filter.BaseFee != nil {
|
||||||
if tx.ExecFeeCap.Lt(filter.BaseFee) {
|
if tx.execFeeCap.Lt(filter.BaseFee) {
|
||||||
break // basefee too low, cannot be included, discard rest of txs from the account
|
break // basefee too low, cannot be included, discard rest of txs from the account
|
||||||
}
|
}
|
||||||
tip := new(uint256.Int).Sub(tx.ExecFeeCap, filter.BaseFee)
|
tip := new(uint256.Int).Sub(tx.execFeeCap, filter.BaseFee)
|
||||||
if tip.Gt(tx.ExecTipCap) {
|
if tip.Gt(tx.execTipCap) {
|
||||||
tip = tx.ExecTipCap
|
tip = tx.execTipCap
|
||||||
}
|
}
|
||||||
if tip.Lt(filter.MinTip) {
|
if tip.Lt(filter.MinTip) {
|
||||||
break // allowed or remaining tip too low, cannot be included, discard rest of txs from the account
|
break // allowed or remaining tip too low, cannot be included, discard rest of txs from the account
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if filter.BlobFee != nil {
|
if filter.BlobFee != nil {
|
||||||
if tx.BlobFeeCap.Lt(filter.BlobFee) {
|
if tx.blobFeeCap.Lt(filter.BlobFee) {
|
||||||
break // blobfee too low, cannot be included, discard rest of txs from the account
|
break // blobfee too low, cannot be included, discard rest of txs from the account
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if filter.GasLimitCap != 0 {
|
if filter.GasLimitCap != 0 {
|
||||||
if tx.ExecGas > filter.GasLimitCap {
|
if tx.execGas > filter.GasLimitCap {
|
||||||
break // execution gas limit is too high
|
break // execution gas limit is too high
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Transaction was accepted according to the filter, append to the pending list
|
// Transaction was accepted according to the filter, append to the pending list
|
||||||
lazies = append(lazies, &txpool.LazyTransaction{
|
lazies = append(lazies, &txpool.LazyTransaction{
|
||||||
Pool: p,
|
Pool: p,
|
||||||
Hash: tx.TxHash,
|
Hash: tx.hash,
|
||||||
Time: execStart, // TODO(karalabe): Maybe save these and use that?
|
Time: execStart, // TODO(karalabe): Maybe save these and use that?
|
||||||
GasFeeCap: tx.ExecFeeCap,
|
GasFeeCap: tx.execFeeCap,
|
||||||
GasTipCap: tx.ExecTipCap,
|
GasTipCap: tx.execTipCap,
|
||||||
Gas: tx.ExecGas,
|
Gas: tx.execGas,
|
||||||
BlobGas: tx.BlobGas,
|
BlobGas: tx.blobGas,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if len(lazies) > 0 {
|
if len(lazies) > 0 {
|
||||||
|
|
@ -1790,7 +1790,7 @@ func (p *BlobPool) Nonce(addr common.Address) uint64 {
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
if txs, ok := p.index[addr]; ok {
|
if txs, ok := p.index[addr]; ok {
|
||||||
return txs[len(txs)-1].Nonce + 1
|
return txs[len(txs)-1].nonce + 1
|
||||||
}
|
}
|
||||||
return p.state.GetNonce(addr)
|
return p.state.GetNonce(addr)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -283,10 +283,10 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
|
||||||
seen := make(map[common.Hash]struct{})
|
seen := make(map[common.Hash]struct{})
|
||||||
for addr, txs := range pool.index {
|
for addr, txs := range pool.index {
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
if _, ok := seen[tx.TxHash]; ok {
|
if _, ok := seen[tx.hash]; ok {
|
||||||
t.Errorf("duplicate hash #%x in transaction index: address %s, nonce %d", tx.TxHash, addr, tx.Nonce)
|
t.Errorf("duplicate hash #%x in transaction index: address %s, nonce %d", tx.hash, addr, tx.nonce)
|
||||||
}
|
}
|
||||||
seen[tx.TxHash] = struct{}{}
|
seen[tx.hash] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for hash, id := range pool.lookup.txIndex {
|
for hash, id := range pool.lookup.txIndex {
|
||||||
|
|
@ -302,11 +302,11 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
|
||||||
blobs := make(map[common.Hash]map[common.Hash]struct{})
|
blobs := make(map[common.Hash]map[common.Hash]struct{})
|
||||||
for _, txs := range pool.index {
|
for _, txs := range pool.index {
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
for _, vhash := range tx.VHashes {
|
for _, vhash := range tx.vhashes {
|
||||||
if blobs[vhash] == nil {
|
if blobs[vhash] == nil {
|
||||||
blobs[vhash] = make(map[common.Hash]struct{})
|
blobs[vhash] = make(map[common.Hash]struct{})
|
||||||
}
|
}
|
||||||
blobs[vhash][tx.TxHash] = struct{}{}
|
blobs[vhash][tx.hash] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,18 +328,18 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
|
||||||
// and that the first nonce is the next expected one based on the state.
|
// and that the first nonce is the next expected one based on the state.
|
||||||
for addr, txs := range pool.index {
|
for addr, txs := range pool.index {
|
||||||
for i := 1; i < len(txs); i++ {
|
for i := 1; i < len(txs); i++ {
|
||||||
if txs[i].Nonce != txs[i-1].Nonce+1 {
|
if txs[i].nonce != txs[i-1].nonce+1 {
|
||||||
t.Errorf("addr %v, tx %d nonce mismatch: have %d, want %d", addr, i, txs[i].Nonce, txs[i-1].Nonce+1)
|
t.Errorf("addr %v, tx %d nonce mismatch: have %d, want %d", addr, i, txs[i].nonce, txs[i-1].nonce+1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if txs[0].Nonce != pool.state.GetNonce(addr) {
|
if txs[0].nonce != pool.state.GetNonce(addr) {
|
||||||
t.Errorf("addr %v, first tx nonce mismatch: have %d, want %d", addr, txs[0].Nonce, pool.state.GetNonce(addr))
|
t.Errorf("addr %v, first tx nonce mismatch: have %d, want %d", addr, txs[0].nonce, pool.state.GetNonce(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Verify that calculated evacuation thresholds are correct
|
// Verify that calculated evacuation thresholds are correct
|
||||||
for addr, txs := range pool.index {
|
for addr, txs := range pool.index {
|
||||||
if !txs[0].evictionExecTip.Eq(txs[0].ExecTipCap) {
|
if !txs[0].evictionExecTip.Eq(txs[0].execTipCap) {
|
||||||
t.Errorf("addr %v, tx %d eviction execution tip mismatch: have %d, want %d", addr, 0, txs[0].evictionExecTip, txs[0].ExecTipCap)
|
t.Errorf("addr %v, tx %d eviction execution tip mismatch: have %d, want %d", addr, 0, txs[0].evictionExecTip, txs[0].execTipCap)
|
||||||
}
|
}
|
||||||
if math.Abs(txs[0].evictionExecFeeJumps-txs[0].basefeeJumps) > 0.001 {
|
if math.Abs(txs[0].evictionExecFeeJumps-txs[0].basefeeJumps) > 0.001 {
|
||||||
t.Errorf("addr %v, tx %d eviction execution fee jumps mismatch: have %f, want %f", addr, 0, txs[0].evictionExecFeeJumps, txs[0].basefeeJumps)
|
t.Errorf("addr %v, tx %d eviction execution fee jumps mismatch: have %f, want %f", addr, 0, txs[0].evictionExecFeeJumps, txs[0].basefeeJumps)
|
||||||
|
|
@ -349,8 +349,8 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
|
||||||
}
|
}
|
||||||
for i := 1; i < len(txs); i++ {
|
for i := 1; i < len(txs); i++ {
|
||||||
wantExecTip := txs[i-1].evictionExecTip
|
wantExecTip := txs[i-1].evictionExecTip
|
||||||
if wantExecTip.Gt(txs[i].ExecTipCap) {
|
if wantExecTip.Gt(txs[i].execTipCap) {
|
||||||
wantExecTip = txs[i].ExecTipCap
|
wantExecTip = txs[i].execTipCap
|
||||||
}
|
}
|
||||||
if !txs[i].evictionExecTip.Eq(wantExecTip) {
|
if !txs[i].evictionExecTip.Eq(wantExecTip) {
|
||||||
t.Errorf("addr %v, tx %d eviction execution tip mismatch: have %d, want %d", addr, i, txs[i].evictionExecTip, wantExecTip)
|
t.Errorf("addr %v, tx %d eviction execution tip mismatch: have %d, want %d", addr, i, txs[i].evictionExecTip, wantExecTip)
|
||||||
|
|
@ -377,7 +377,7 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
|
||||||
for addr, txs := range pool.index {
|
for addr, txs := range pool.index {
|
||||||
spent := new(uint256.Int)
|
spent := new(uint256.Int)
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
spent.Add(spent, tx.CostCap)
|
spent.Add(spent, tx.costCap)
|
||||||
}
|
}
|
||||||
if !pool.spent[addr].Eq(spent) {
|
if !pool.spent[addr].Eq(spent) {
|
||||||
t.Errorf("addr %v expenditure mismatch: have %d, want %d", addr, pool.spent[addr], spent)
|
t.Errorf("addr %v expenditure mismatch: have %d, want %d", addr, pool.spent[addr], spent)
|
||||||
|
|
@ -387,7 +387,7 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
|
||||||
var stored uint64
|
var stored uint64
|
||||||
for _, txs := range pool.index {
|
for _, txs := range pool.index {
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
stored += uint64(tx.StorageSize)
|
stored += uint64(tx.storageSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pool.stored != stored {
|
if pool.stored != stored {
|
||||||
|
|
@ -410,7 +410,7 @@ func verifyBlobRetrievals(t *testing.T, pool *BlobPool) {
|
||||||
)
|
)
|
||||||
for _, txs := range pool.index {
|
for _, txs := range pool.index {
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
for _, vhash := range tx.VHashes {
|
for _, vhash := range tx.vhashes {
|
||||||
known[vhash] = struct{}{}
|
known[vhash] = struct{}{}
|
||||||
}
|
}
|
||||||
hashes = append(hashes, tx.vhashes...)
|
hashes = append(hashes, tx.vhashes...)
|
||||||
|
|
@ -721,36 +721,36 @@ func TestOpenDrops(t *testing.T) {
|
||||||
alive := make(map[uint64]struct{})
|
alive := make(map[uint64]struct{})
|
||||||
for _, txs := range pool.index {
|
for _, txs := range pool.index {
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
switch tx.Id {
|
switch tx.id {
|
||||||
case malformed:
|
case malformed:
|
||||||
t.Errorf("malformed RLP transaction remained in storage")
|
t.Errorf("malformed RLP transaction remained in storage")
|
||||||
case badsig:
|
case badsig:
|
||||||
t.Errorf("invalidly signed transaction remained in storage")
|
t.Errorf("invalidly signed transaction remained in storage")
|
||||||
default:
|
default:
|
||||||
if _, ok := dangling[tx.Id]; ok {
|
if _, ok := dangling[tx.id]; ok {
|
||||||
t.Errorf("dangling transaction remained in storage: %d", tx.Id)
|
t.Errorf("dangling transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := filled[tx.Id]; ok {
|
} else if _, ok := filled[tx.id]; ok {
|
||||||
t.Errorf("filled transaction remained in storage: %d", tx.Id)
|
t.Errorf("filled transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := overlapped[tx.Id]; ok {
|
} else if _, ok := overlapped[tx.id]; ok {
|
||||||
t.Errorf("overlapped transaction remained in storage: %d", tx.Id)
|
t.Errorf("overlapped transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := gapped[tx.Id]; ok {
|
} else if _, ok := gapped[tx.id]; ok {
|
||||||
t.Errorf("gapped transaction remained in storage: %d", tx.Id)
|
t.Errorf("gapped transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := underpaid[tx.Id]; ok {
|
} else if _, ok := underpaid[tx.id]; ok {
|
||||||
t.Errorf("underpaid transaction remained in storage: %d", tx.Id)
|
t.Errorf("underpaid transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := outpriced[tx.Id]; ok {
|
} else if _, ok := outpriced[tx.id]; ok {
|
||||||
t.Errorf("outpriced transaction remained in storage: %d", tx.Id)
|
t.Errorf("outpriced transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := exceeded[tx.Id]; ok {
|
} else if _, ok := exceeded[tx.id]; ok {
|
||||||
t.Errorf("fully overdrafted transaction remained in storage: %d", tx.Id)
|
t.Errorf("fully overdrafted transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := overdrafted[tx.Id]; ok {
|
} else if _, ok := overdrafted[tx.id]; ok {
|
||||||
t.Errorf("partially overdrafted transaction remained in storage: %d", tx.Id)
|
t.Errorf("partially overdrafted transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := overcapped[tx.Id]; ok {
|
} else if _, ok := overcapped[tx.id]; ok {
|
||||||
t.Errorf("overcapped transaction remained in storage: %d", tx.Id)
|
t.Errorf("overcapped transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := duplicated[tx.Id]; ok {
|
} else if _, ok := duplicated[tx.id]; ok {
|
||||||
t.Errorf("duplicated transaction remained in storage: %d", tx.Id)
|
t.Errorf("duplicated transaction remained in storage: %d", tx.id)
|
||||||
} else if _, ok := repeated[tx.Id]; ok {
|
} else if _, ok := repeated[tx.id]; ok {
|
||||||
t.Errorf("repeated Nonce transaction remained in storage: %d", tx.Id)
|
t.Errorf("repeated nonce transaction remained in storage: %d", tx.id)
|
||||||
} else {
|
} else {
|
||||||
alive[tx.Id] = struct{}{}
|
alive[tx.id] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -836,8 +836,8 @@ func TestOpenIndex(t *testing.T) {
|
||||||
|
|
||||||
// Verify that the transactions have been sorted by nonce (case 1)
|
// Verify that the transactions have been sorted by nonce (case 1)
|
||||||
for i := 0; i < len(pool.index[addr]); i++ {
|
for i := 0; i < len(pool.index[addr]); i++ {
|
||||||
if pool.index[addr][i].Nonce != uint64(i) {
|
if pool.index[addr][i].nonce != uint64(i) {
|
||||||
t.Errorf("tx %d nonce mismatch: have %d, want %d", i, pool.index[addr][i].Nonce, uint64(i))
|
t.Errorf("tx %d nonce mismatch: have %d, want %d", i, pool.index[addr][i].nonce, uint64(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Verify that the cumulative fee minimums have been correctly calculated (case 2)
|
// Verify that the cumulative fee minimums have been correctly calculated (case 2)
|
||||||
|
|
|
||||||
|
|
@ -145,12 +145,12 @@ func TestPriceHeapSorting(t *testing.T) {
|
||||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||||
)
|
)
|
||||||
index[addr] = []*blobTxMeta{{
|
index[addr] = []*blobTxMeta{{
|
||||||
Id: uint64(j),
|
id: uint64(j),
|
||||||
StorageSize: 128 * 1024,
|
storageSize: 128 * 1024,
|
||||||
Nonce: 0,
|
nonce: 0,
|
||||||
ExecTipCap: execTip,
|
execTipCap: execTip,
|
||||||
ExecFeeCap: execFee,
|
execFeeCap: execFee,
|
||||||
BlobFeeCap: blobFee,
|
blobFeeCap: blobFee,
|
||||||
basefeeJumps: basefeeJumps,
|
basefeeJumps: basefeeJumps,
|
||||||
blobfeeJumps: blobfeeJumps,
|
blobfeeJumps: blobfeeJumps,
|
||||||
evictionExecTip: execTip,
|
evictionExecTip: execTip,
|
||||||
|
|
@ -204,12 +204,12 @@ func benchmarkPriceHeapReinit(b *testing.B, datacap uint64) {
|
||||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||||
)
|
)
|
||||||
index[addr] = []*blobTxMeta{{
|
index[addr] = []*blobTxMeta{{
|
||||||
Id: uint64(i),
|
id: uint64(i),
|
||||||
StorageSize: 128 * 1024,
|
storageSize: 128 * 1024,
|
||||||
Nonce: 0,
|
nonce: 0,
|
||||||
ExecTipCap: execTip,
|
execTipCap: execTip,
|
||||||
ExecFeeCap: execFee,
|
execFeeCap: execFee,
|
||||||
BlobFeeCap: blobFee,
|
blobFeeCap: blobFee,
|
||||||
basefeeJumps: basefeeJumps,
|
basefeeJumps: basefeeJumps,
|
||||||
blobfeeJumps: blobfeeJumps,
|
blobfeeJumps: blobfeeJumps,
|
||||||
evictionExecTip: execTip,
|
evictionExecTip: execTip,
|
||||||
|
|
@ -280,12 +280,12 @@ func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) {
|
||||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||||
)
|
)
|
||||||
index[addr] = []*blobTxMeta{{
|
index[addr] = []*blobTxMeta{{
|
||||||
Id: uint64(i),
|
id: uint64(i),
|
||||||
StorageSize: 128 * 1024,
|
storageSize: 128 * 1024,
|
||||||
Nonce: 0,
|
nonce: 0,
|
||||||
ExecTipCap: execTip,
|
execTipCap: execTip,
|
||||||
ExecFeeCap: execFee,
|
execFeeCap: execFee,
|
||||||
BlobFeeCap: blobFee,
|
blobFeeCap: blobFee,
|
||||||
basefeeJumps: basefeeJumps,
|
basefeeJumps: basefeeJumps,
|
||||||
blobfeeJumps: blobfeeJumps,
|
blobfeeJumps: blobfeeJumps,
|
||||||
evictionExecTip: execTip,
|
evictionExecTip: execTip,
|
||||||
|
|
@ -311,12 +311,12 @@ func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) {
|
||||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||||
)
|
)
|
||||||
metas[i] = &blobTxMeta{
|
metas[i] = &blobTxMeta{
|
||||||
Id: uint64(int(blobs) + i),
|
id: uint64(int(blobs) + i),
|
||||||
StorageSize: 128 * 1024,
|
storageSize: 128 * 1024,
|
||||||
Nonce: 0,
|
nonce: 0,
|
||||||
ExecTipCap: execTip,
|
execTipCap: execTip,
|
||||||
ExecFeeCap: execFee,
|
execFeeCap: execFee,
|
||||||
BlobFeeCap: blobFee,
|
blobFeeCap: blobFee,
|
||||||
basefeeJumps: basefeeJumps,
|
basefeeJumps: basefeeJumps,
|
||||||
blobfeeJumps: blobfeeJumps,
|
blobfeeJumps: blobfeeJumps,
|
||||||
evictionExecTip: execTip,
|
evictionExecTip: execTip,
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ func (l *limbo) parseBlob(id uint64, data []byte) error {
|
||||||
log.Error("Failed to decode blob limbo entry", "id", id, "err", err)
|
log.Error("Failed to decode blob limbo entry", "id", id, "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
txHash := item.BlobTxMeta.TxHash
|
txHash := item.BlobTxMeta.hash
|
||||||
if _, ok := l.index[txHash]; ok {
|
if _, ok := l.index[txHash]; ok {
|
||||||
// This path is impossible, unless due to a programming error a blob gets
|
// This path is impossible, unless due to a programming error a blob gets
|
||||||
// inserted into the limbo which was already part of if. Recover gracefully
|
// inserted into the limbo which was already part of if. Recover gracefully
|
||||||
|
|
@ -121,10 +121,10 @@ func (l *limbo) finalize(final *types.Header, fn func(id uint64, txHash common.H
|
||||||
if err := l.store.Delete(id); err != nil {
|
if err := l.store.Delete(id); err != nil {
|
||||||
log.Error("Failed to drop finalized blob", "block", item.Block, "id", id, "err", err)
|
log.Error("Failed to drop finalized blob", "block", item.Block, "id", id, "err", err)
|
||||||
}
|
}
|
||||||
delete(l.index, item.BlobTxMeta.TxHash)
|
delete(l.index, item.BlobTxMeta.hash)
|
||||||
delete(l.limbos, id)
|
delete(l.limbos, id)
|
||||||
if fn != nil { // Delete blob tx if fn is not null.
|
if fn != nil { // Delete blob tx if fn is not null.
|
||||||
fn(item.BlobTxMeta.Id, item.BlobTxMeta.TxHash)
|
fn(item.BlobTxMeta.id, item.BlobTxMeta.hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,12 +134,12 @@ func (l *limbo) finalize(final *types.Header, fn func(id uint64, txHash common.H
|
||||||
func (l *limbo) push(metaData *blobTxMeta, block uint64) error {
|
func (l *limbo) push(metaData *blobTxMeta, block uint64) error {
|
||||||
// If the blobs are already tracked by the limbo, consider it a programming
|
// If the blobs are already tracked by the limbo, consider it a programming
|
||||||
// error. There's not much to do against it, but be loud.
|
// error. There's not much to do against it, but be loud.
|
||||||
if _, ok := l.index[metaData.TxHash]; ok {
|
if _, ok := l.index[metaData.hash]; ok {
|
||||||
log.Error("Limbo cannot push already tracked blobs", "tx", metaData.TxHash)
|
log.Error("Limbo cannot push already tracked blobs", "tx", metaData.hash)
|
||||||
return errors.New("already tracked blob transaction")
|
return errors.New("already tracked blob transaction")
|
||||||
}
|
}
|
||||||
if err := l.setAndIndex(metaData, block); err != nil {
|
if err := l.setAndIndex(metaData, block); err != nil {
|
||||||
log.Error("Failed to set and index limboed blobs", "tx", metaData.TxHash, "err", err)
|
log.Error("Failed to set and index limboed blobs", "tx", metaData.hash, "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -163,8 +163,8 @@ func (l *limbo) pull(tx common.Hash) (*blobTxMeta, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
meta := item.BlobTxMeta
|
meta := item.BlobTxMeta
|
||||||
meta.basefeeJumps = dynamicFeeJumps(meta.ExecFeeCap)
|
meta.basefeeJumps = dynamicFeeJumps(meta.execFeeCap)
|
||||||
meta.blobfeeJumps = dynamicFeeJumps(meta.BlobFeeCap)
|
meta.blobfeeJumps = dynamicFeeJumps(meta.blobFeeCap)
|
||||||
return meta, nil
|
return meta, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,7 +208,7 @@ func (l *limbo) update(txhash common.Hash, block uint64) {
|
||||||
// the store and indices.
|
// the store and indices.
|
||||||
func (l *limbo) getAndDrop(id uint64) (*limboBlob, error) {
|
func (l *limbo) getAndDrop(id uint64) (*limboBlob, error) {
|
||||||
item := l.limbos[id]
|
item := l.limbos[id]
|
||||||
delete(l.index, item.BlobTxMeta.TxHash)
|
delete(l.index, item.BlobTxMeta.hash)
|
||||||
delete(l.limbos, id)
|
delete(l.limbos, id)
|
||||||
if err := l.store.Delete(id); err != nil {
|
if err := l.store.Delete(id); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -231,7 +231,7 @@ func (l *limbo) setAndIndex(metaData *blobTxMeta, block uint64) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
l.index[item.BlobTxMeta.TxHash] = id
|
l.index[item.BlobTxMeta.hash] = id
|
||||||
l.limbos[id] = item
|
l.limbos[id] = item
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,16 +83,16 @@ func (l *lookup) sizeOfTx(txhash common.Hash) (uint64, bool) {
|
||||||
// hashes; and from transaction hashes to datastore storage item ids.
|
// hashes; and from transaction hashes to datastore storage item ids.
|
||||||
func (l *lookup) track(tx *blobTxMeta) {
|
func (l *lookup) track(tx *blobTxMeta) {
|
||||||
// Map all the blobs to the transaction hash
|
// Map all the blobs to the transaction hash
|
||||||
for _, vhash := range tx.VHashes {
|
for _, vhash := range tx.vhashes {
|
||||||
if _, ok := l.blobIndex[vhash]; !ok {
|
if _, ok := l.blobIndex[vhash]; !ok {
|
||||||
l.blobIndex[vhash] = make(map[common.Hash]struct{})
|
l.blobIndex[vhash] = make(map[common.Hash]struct{})
|
||||||
}
|
}
|
||||||
l.blobIndex[vhash][tx.TxHash] = struct{}{} // may be double mapped if a tx contains the same blob twice
|
l.blobIndex[vhash][tx.hash] = struct{}{} // may be double mapped if a tx contains the same blob twice
|
||||||
}
|
}
|
||||||
// Map the transaction hash to the datastore id and RLP-encoded transaction size
|
// Map the transaction hash to the datastore id and RLP-encoded transaction size
|
||||||
l.txIndex[tx.TxHash] = &txMetadata{
|
l.txIndex[tx.hash] = &txMetadata{
|
||||||
id: tx.Id,
|
id: tx.id,
|
||||||
size: tx.Size,
|
size: tx.size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,11 +100,11 @@ func (l *lookup) track(tx *blobTxMeta) {
|
||||||
// hashes from the blob index.
|
// hashes from the blob index.
|
||||||
func (l *lookup) untrack(tx *blobTxMeta) {
|
func (l *lookup) untrack(tx *blobTxMeta) {
|
||||||
// Unmap the transaction hash from the datastore id
|
// Unmap the transaction hash from the datastore id
|
||||||
delete(l.txIndex, tx.TxHash)
|
delete(l.txIndex, tx.hash)
|
||||||
|
|
||||||
// Unmap all the blobs from the transaction hash
|
// Unmap all the blobs from the transaction hash
|
||||||
for _, vhash := range tx.VHashes {
|
for _, vhash := range tx.vhashes {
|
||||||
delete(l.blobIndex[vhash], tx.TxHash) // may be double deleted if a tx contains the same blob twice
|
delete(l.blobIndex[vhash], tx.hash) // may be double deleted if a tx contains the same blob twice
|
||||||
if len(l.blobIndex[vhash]) == 0 {
|
if len(l.blobIndex[vhash]) == 0 {
|
||||||
delete(l.blobIndex, vhash)
|
delete(l.blobIndex, vhash)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue