Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
dea71556
Unverified
Commit
dea71556
authored
Jul 08, 2021
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eth/gasprice, internal/ethapi, miner: minor feehistory fixes
parent
5441a8fa
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
108 additions
and
100 deletions
+108
-100
feehistory.go
eth/gasprice/feehistory.go
+88
-81
feehistory_test.go
eth/gasprice/feehistory_test.go
+3
-2
api.go
internal/ethapi/api.go
+15
-15
worker.go
miner/worker.go
+2
-2
No files found.
eth/gasprice/feehistory.go
View file @
dea71556
...
...
@@ -19,6 +19,7 @@ package gasprice
import
(
"context"
"errors"
"fmt"
"math/big"
"sort"
"sync/atomic"
...
...
@@ -30,11 +31,19 @@ import (
)
var
(
errInvalidPercentile
s
=
errors
.
New
(
"Invalid reward percentiles
"
)
errRequestBeyondHead
=
errors
.
New
(
"R
equest beyond head block"
)
errInvalidPercentile
=
errors
.
New
(
"invalid reward percentile
"
)
errRequestBeyondHead
=
errors
.
New
(
"r
equest beyond head block"
)
)
const
maxBlockCount
=
1024
// number of blocks retrievable with a single query
const
(
// maxFeeHistory is the maximum number of blocks that can be retrieved for a
// fee history request.
maxFeeHistory
=
1024
// maxBlockFetchers is the max number of goroutines to spin up to pull blocks
// for the fee history calculation (mostly relevant for LES).
maxBlockFetchers
=
4
)
// blockFees represents a single block for processing
type
blockFees
struct
{
...
...
@@ -124,23 +133,22 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
// also returned if requested and available.
// Note: an error is only returned if retrieving the head header has failed. If there are no
// retrievable blocks in the specified range then zero block count is returned with no error.
func
(
oracle
*
Oracle
)
resolveBlockRange
(
ctx
context
.
Context
,
lastBlock
Number
rpc
.
BlockNumber
,
blockCount
,
maxHistory
int
)
(
*
types
.
Block
,
types
.
Receipts
,
rpc
.
BlockNumber
,
int
,
error
)
{
func
(
oracle
*
Oracle
)
resolveBlockRange
(
ctx
context
.
Context
,
lastBlock
rpc
.
BlockNumber
,
blocks
,
maxHistory
int
)
(
*
types
.
Block
,
[]
*
types
.
Receipt
,
rpc
.
BlockNumber
,
int
,
error
)
{
var
(
headBlock
Number
rpc
.
BlockNumber
headBlock
rpc
.
BlockNumber
pendingBlock
*
types
.
Block
pendingReceipts
types
.
Receipts
)
// query either pending block or head header and set headBlockNumber
if
lastBlockNumber
==
rpc
.
PendingBlockNumber
{
// query either pending block or head header and set headBlock
if
lastBlock
==
rpc
.
PendingBlockNumber
{
if
pendingBlock
,
pendingReceipts
=
oracle
.
backend
.
PendingBlockAndReceipts
();
pendingBlock
!=
nil
{
lastBlock
Number
=
rpc
.
BlockNumber
(
pendingBlock
.
NumberU64
())
headBlock
Number
=
lastBlockNumber
-
1
lastBlock
=
rpc
.
BlockNumber
(
pendingBlock
.
NumberU64
())
headBlock
=
lastBlock
-
1
}
else
{
// pending block not supported by backend, process until latest block
lastBlock
Number
=
rpc
.
LatestBlockNumber
block
Count
--
if
block
Count
==
0
{
lastBlock
=
rpc
.
LatestBlockNumber
block
s
--
if
block
s
==
0
{
return
nil
,
nil
,
0
,
0
,
nil
}
}
...
...
@@ -148,32 +156,32 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlockNumber rpc
if
pendingBlock
==
nil
{
// if pending block is not fetched then we retrieve the head header to get the head block number
if
latestHeader
,
err
:=
oracle
.
backend
.
HeaderByNumber
(
ctx
,
rpc
.
LatestBlockNumber
);
err
==
nil
{
headBlock
Number
=
rpc
.
BlockNumber
(
latestHeader
.
Number
.
Uint64
())
headBlock
=
rpc
.
BlockNumber
(
latestHeader
.
Number
.
Uint64
())
}
else
{
return
nil
,
nil
,
0
,
0
,
err
}
}
if
lastBlock
Number
==
rpc
.
LatestBlockNumber
{
lastBlock
Number
=
headBlockNumber
}
else
if
pendingBlock
==
nil
&&
lastBlock
Number
>
headBlockNumber
{
return
nil
,
nil
,
0
,
0
,
errRequestBeyondHead
if
lastBlock
==
rpc
.
LatestBlockNumber
{
lastBlock
=
headBlock
}
else
if
pendingBlock
==
nil
&&
lastBlock
>
headBlock
{
return
nil
,
nil
,
0
,
0
,
fmt
.
Errorf
(
"%w: requested %d, head %d"
,
errRequestBeyondHead
,
lastBlock
,
headBlock
)
}
if
maxHistory
!=
0
{
// limit retrieval to the given number of latest blocks
if
tooOldCount
:=
int64
(
headBlock
Number
)
-
int64
(
maxHistory
)
-
int64
(
lastBlockNumber
)
+
int64
(
blockCount
);
tooOldCount
>
0
{
if
tooOldCount
:=
int64
(
headBlock
)
-
int64
(
maxHistory
)
-
int64
(
lastBlock
)
+
int64
(
blocks
);
tooOldCount
>
0
{
// tooOldCount is the number of requested blocks that are too old to be served
if
int64
(
block
Count
)
>
tooOldCount
{
block
Count
-=
int
(
tooOldCount
)
if
int64
(
block
s
)
>
tooOldCount
{
block
s
-=
int
(
tooOldCount
)
}
else
{
return
nil
,
nil
,
0
,
0
,
nil
}
}
}
// ensure not trying to retrieve before genesis
if
rpc
.
BlockNumber
(
block
Count
)
>
lastBlockNumber
+
1
{
block
Count
=
int
(
lastBlockNumber
+
1
)
if
rpc
.
BlockNumber
(
block
s
)
>
lastBlock
+
1
{
block
s
=
int
(
lastBlock
+
1
)
}
return
pendingBlock
,
pendingReceipts
,
lastBlock
Number
,
blockCount
,
nil
return
pendingBlock
,
pendingReceipts
,
lastBlock
,
blocks
,
nil
}
// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
...
...
@@ -189,90 +197,89 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlockNumber rpc
// - gasUsedRatio: gasUsed/gasLimit in the given block
// Note: baseFee includes the next block after the newest of the returned range, because this
// value can be derived from the newest block.
func
(
oracle
*
Oracle
)
FeeHistory
(
ctx
context
.
Context
,
blockCount
int
,
lastBlockNumber
rpc
.
BlockNumber
,
rewardPercentiles
[]
float64
)
(
firstBlockNumber
rpc
.
BlockNumber
,
reward
[][]
*
big
.
Int
,
baseFee
[]
*
big
.
Int
,
gasUsedRatio
[]
float64
,
err
error
)
{
if
blockCount
<
1
{
// returning with no data and no error means there are no retrievable blocks
return
func
(
oracle
*
Oracle
)
FeeHistory
(
ctx
context
.
Context
,
blocks
int
,
lastBlock
rpc
.
BlockNumber
,
rewardPercentiles
[]
float64
)
(
rpc
.
BlockNumber
,
[][]
*
big
.
Int
,
[]
*
big
.
Int
,
[]
float64
,
error
)
{
if
blocks
<
1
{
return
0
,
nil
,
nil
,
nil
,
nil
// returning with no data and no error means there are no retrievable blocks
}
if
blockCount
>
maxBlockCount
{
blockCount
=
maxBlockCount
if
blocks
>
maxFeeHistory
{
log
.
Warn
(
"Sanitizing fee history length"
,
"requested"
,
blocks
,
"truncated"
,
maxFeeHistory
)
blocks
=
maxFeeHistory
}
for
i
,
p
:=
range
rewardPercentiles
{
if
p
<
0
||
p
>
100
||
(
i
>
0
&&
p
<
rewardPercentiles
[
i
-
1
])
{
return
0
,
nil
,
nil
,
nil
,
errInvalidPercentiles
if
p
<
0
||
p
>
100
{
return
0
,
nil
,
nil
,
nil
,
fmt
.
Errorf
(
"%w: %f"
,
errInvalidPercentile
,
p
)
}
if
i
>
0
&&
p
<
rewardPercentiles
[
i
-
1
]
{
return
0
,
nil
,
nil
,
nil
,
fmt
.
Errorf
(
"%w: #%d:%f > #%d:%f"
,
errInvalidPercentile
,
i
-
1
,
rewardPercentiles
[
i
-
1
],
i
,
p
)
}
processBlocks
:=
len
(
rewardPercentiles
)
!=
0
// limit retrieval to maxHistory if set
var
maxHistory
int
if
processBlocks
{
}
// Only process blocks if reward percentiles were requested
maxHistory
:=
oracle
.
maxHeaderHistory
if
len
(
rewardPercentiles
)
!=
0
{
maxHistory
=
oracle
.
maxBlockHistory
}
else
{
maxHistory
=
oracle
.
maxHeaderHistory
}
var
(
pendingBlock
*
types
.
Block
pendingReceipts
types
.
Receipts
pendingReceipts
[]
*
types
.
Receipt
err
error
)
if
pendingBlock
,
pendingReceipts
,
lastBlockNumber
,
blockCount
,
err
=
oracle
.
resolveBlockRange
(
ctx
,
lastBlockNumber
,
blockCount
,
maxHistory
);
err
!=
nil
||
blockCount
==
0
{
return
pendingBlock
,
pendingReceipts
,
lastBlock
,
blocks
,
err
=
oracle
.
resolveBlockRange
(
ctx
,
lastBlock
,
blocks
,
maxHistory
)
if
err
!=
nil
||
blocks
==
0
{
return
0
,
nil
,
nil
,
nil
,
err
}
firstBlockNumber
=
lastBlockNumber
+
1
-
rpc
.
BlockNumber
(
blockCount
)
oldestBlock
:=
lastBlock
+
1
-
rpc
.
BlockNumber
(
blocks
)
processNext
:=
int64
(
firstBlockNumber
)
resultCh
:=
make
(
chan
*
blockFees
,
blockCount
)
threadCount
:=
4
if
blockCount
<
threadCount
{
threadCount
=
blockCount
}
for
i
:=
0
;
i
<
threadCount
;
i
++
{
var
(
next
=
int64
(
oldestBlock
)
results
=
make
(
chan
*
blockFees
,
blocks
)
)
for
i
:=
0
;
i
<
maxBlockFetchers
&&
i
<
blocks
;
i
++
{
go
func
()
{
for
{
blockNumber
:=
rpc
.
BlockNumber
(
atomic
.
AddInt64
(
&
processNext
,
1
)
-
1
)
if
blockNumber
>
lastBlockNumber
{
// Retrieve the next block number to fetch with this goroutine
blockNumber
:=
rpc
.
BlockNumber
(
atomic
.
AddInt64
(
&
next
,
1
)
-
1
)
if
blockNumber
>
lastBlock
{
return
}
bf
:=
&
blockFees
{
blockNumber
:
blockNumber
}
fees
:=
&
blockFees
{
blockNumber
:
blockNumber
}
if
pendingBlock
!=
nil
&&
blockNumber
>=
rpc
.
BlockNumber
(
pendingBlock
.
NumberU64
())
{
bf
.
block
,
bf
.
receipts
=
pendingBlock
,
pendingReceipts
fees
.
block
,
fees
.
receipts
=
pendingBlock
,
pendingReceipts
}
else
{
if
processBlocks
{
bf
.
block
,
bf
.
err
=
oracle
.
backend
.
BlockByNumber
(
ctx
,
blockNumber
)
if
bf
.
block
!
=
nil
{
bf
.
receipts
,
bf
.
err
=
oracle
.
backend
.
GetReceipts
(
ctx
,
bf
.
block
.
Hash
())
if
len
(
rewardPercentiles
)
!=
0
{
fees
.
block
,
fees
.
err
=
oracle
.
backend
.
BlockByNumber
(
ctx
,
blockNumber
)
if
fees
.
block
!=
nil
&&
fees
.
err
=
=
nil
{
fees
.
receipts
,
fees
.
err
=
oracle
.
backend
.
GetReceipts
(
ctx
,
fees
.
block
.
Hash
())
}
}
else
{
bf
.
header
,
bf
.
err
=
oracle
.
backend
.
HeaderByNumber
(
ctx
,
blockNumber
)
fees
.
header
,
fees
.
err
=
oracle
.
backend
.
HeaderByNumber
(
ctx
,
blockNumber
)
}
}
if
bf
.
block
!=
nil
{
bf
.
header
=
bf
.
block
.
Header
()
if
fees
.
block
!=
nil
{
fees
.
header
=
fees
.
block
.
Header
()
}
if
bf
.
header
!=
nil
{
oracle
.
processBlock
(
bf
,
rewardPercentiles
)
if
fees
.
header
!=
nil
{
oracle
.
processBlock
(
fees
,
rewardPercentiles
)
}
// send to result
Ch even if empty to guarantee that blockCount
items are sent in total
result
Ch
<-
bf
// send to result
s even if empty to guarantee that blocks
items are sent in total
result
s
<-
fees
}
}()
}
reward
=
make
([][]
*
big
.
Int
,
blockCount
)
baseFee
=
make
([]
*
big
.
Int
,
blockCount
+
1
)
gasUsedRatio
=
make
([]
float64
,
blockCount
)
firstMissing
:=
blockCount
for
;
block
Count
>
0
;
blockCount
--
{
bf
:=
<-
resultCh
if
bf
.
err
!=
nil
{
return
0
,
nil
,
nil
,
nil
,
bf
.
err
}
i
:=
int
(
bf
.
blockNumber
-
firstBlockNumber
)
if
bf
.
header
!=
nil
{
reward
[
i
],
baseFee
[
i
],
baseFee
[
i
+
1
],
gasUsedRatio
[
i
]
=
bf
.
reward
,
bf
.
baseFee
,
bf
.
nextBaseFee
,
bf
.
gasUsedRatio
var
(
reward
=
make
([][]
*
big
.
Int
,
blocks
)
baseFee
=
make
([]
*
big
.
Int
,
blocks
+
1
)
gasUsedRatio
=
make
([]
float64
,
blocks
)
firstMissing
=
blocks
)
for
;
block
s
>
0
;
blocks
--
{
fees
:=
<-
results
if
fees
.
err
!=
nil
{
return
0
,
nil
,
nil
,
nil
,
fees
.
err
}
i
:=
int
(
fees
.
blockNumber
-
oldestBlock
)
if
fees
.
header
!=
nil
{
reward
[
i
],
baseFee
[
i
],
baseFee
[
i
+
1
],
gasUsedRatio
[
i
]
=
fees
.
reward
,
fees
.
baseFee
,
fees
.
nextBaseFee
,
fees
.
gasUsedRatio
}
else
{
// getting no block and no error means we are requesting into the future (might happen because of a reorg)
if
i
<
firstMissing
{
...
...
@@ -283,11 +290,11 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blockCount int, lastBlockN
if
firstMissing
==
0
{
return
0
,
nil
,
nil
,
nil
,
nil
}
if
processBlocks
{
if
len
(
rewardPercentiles
)
!=
0
{
reward
=
reward
[
:
firstMissing
]
}
else
{
reward
=
nil
}
baseFee
,
gasUsedRatio
=
baseFee
[
:
firstMissing
+
1
],
gasUsedRatio
[
:
firstMissing
]
return
return
oldestBlock
,
reward
,
baseFee
,
gasUsedRatio
,
nil
}
eth/gasprice/feehistory_test.go
View file @
dea71556
...
...
@@ -18,6 +18,7 @@ package gasprice
import
(
"context"
"errors"
"math/big"
"testing"
...
...
@@ -37,7 +38,7 @@ func TestFeeHistory(t *testing.T) {
}{
{
false
,
0
,
0
,
10
,
30
,
nil
,
21
,
10
,
nil
},
{
false
,
0
,
0
,
10
,
30
,
[]
float64
{
0
,
10
},
21
,
10
,
nil
},
{
false
,
0
,
0
,
10
,
30
,
[]
float64
{
20
,
10
},
0
,
0
,
errInvalidPercentile
s
},
{
false
,
0
,
0
,
10
,
30
,
[]
float64
{
20
,
10
},
0
,
0
,
errInvalidPercentile
},
{
false
,
0
,
0
,
1000000000
,
30
,
nil
,
0
,
31
,
nil
},
{
false
,
0
,
0
,
1000000000
,
rpc
.
LatestBlockNumber
,
nil
,
0
,
33
,
nil
},
{
false
,
0
,
0
,
10
,
40
,
nil
,
0
,
0
,
errRequestBeyondHead
},
...
...
@@ -81,7 +82,7 @@ func TestFeeHistory(t *testing.T) {
if
len
(
ratio
)
!=
c
.
expCount
{
t
.
Fatalf
(
"Test case %d: gasUsedRatio array length mismatch, want %d, got %d"
,
i
,
c
.
expCount
,
len
(
ratio
))
}
if
err
!=
c
.
expErr
{
if
err
!=
c
.
expErr
&&
!
errors
.
Is
(
err
,
c
.
expErr
)
{
t
.
Fatalf
(
"Test case %d: error mismatch, want %v, got %v"
,
i
,
c
.
expErr
,
err
)
}
}
...
...
internal/ethapi/api.go
View file @
dea71556
...
...
@@ -80,28 +80,28 @@ func (s *PublicEthereumAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.
return
(
*
hexutil
.
Big
)(
tipcap
),
err
}
type
feeHistoryResult
s
struct
{
FirstBlock
rpc
.
BlockNumber
Reward
[][]
*
hexutil
.
Big
BaseFee
[]
*
hexutil
.
Big
GasUsedRatio
[]
float64
type
feeHistoryResult
struct
{
OldestBlock
rpc
.
BlockNumber
`json:"oldestBlock"`
Reward
[][]
*
hexutil
.
Big
`json:"reward,omitempty"`
BaseFee
[]
*
hexutil
.
Big
`json:"baseFeePerGas,omitempty"`
GasUsedRatio
[]
float64
`json:"gasUsedRatio"`
}
func
(
s
*
PublicEthereumAPI
)
FeeHistory
(
ctx
context
.
Context
,
blockCount
int
,
lastBlock
rpc
.
BlockNumber
,
rewardPercentiles
[]
float64
)
(
feeHistoryResults
,
error
)
{
firstBlock
,
reward
,
baseFee
,
gasUsedRatio
,
err
:=
s
.
b
.
FeeHistory
(
ctx
,
blockCount
,
lastBlock
,
rewardPercentiles
)
func
(
s
*
PublicEthereumAPI
)
FeeHistory
(
ctx
context
.
Context
,
blockCount
int
,
lastBlock
rpc
.
BlockNumber
,
rewardPercentiles
[]
float64
)
(
*
feeHistoryResult
,
error
)
{
oldest
,
reward
,
baseFee
,
gasUsed
,
err
:=
s
.
b
.
FeeHistory
(
ctx
,
blockCount
,
lastBlock
,
rewardPercentiles
)
if
err
!=
nil
{
return
feeHistoryResults
{}
,
err
return
nil
,
err
}
results
:=
feeHistoryResults
{
FirstBlock
:
firstBlock
,
GasUsedRatio
:
gasUsed
Ratio
,
results
:=
&
feeHistoryResult
{
OldestBlock
:
oldest
,
GasUsedRatio
:
gasUsed
,
}
if
reward
!=
nil
{
results
.
Reward
=
make
([][]
*
hexutil
.
Big
,
len
(
reward
))
for
j
,
w
:=
range
reward
{
results
.
Reward
[
j
]
=
make
([]
*
hexutil
.
Big
,
len
(
w
))
for
i
,
v
:=
range
w
{
results
.
Reward
[
j
][
i
]
=
(
*
hexutil
.
Big
)(
v
)
for
i
,
w
:=
range
reward
{
results
.
Reward
[
i
]
=
make
([]
*
hexutil
.
Big
,
len
(
w
))
for
j
,
v
:=
range
w
{
results
.
Reward
[
i
][
j
]
=
(
*
hexutil
.
Big
)(
v
)
}
}
}
...
...
miner/worker.go
View file @
dea71556
...
...
@@ -162,7 +162,7 @@ type worker struct {
pendingMu
sync
.
RWMutex
pendingTasks
map
[
common
.
Hash
]
*
task
snapshotMu
sync
.
RWMutex
// The lock used to protect the
block snapshot and state snapshot
snapshotMu
sync
.
RWMutex
// The lock used to protect the
snapshots below
snapshotBlock
*
types
.
Block
snapshotReceipts
types
.
Receipts
snapshotState
*
state
.
StateDB
...
...
@@ -745,7 +745,7 @@ func (w *worker) updateSnapshot() {
w
.
current
.
receipts
,
trie
.
NewStackTrie
(
nil
),
)
w
.
snapshotReceipts
=
w
.
current
.
receipts
w
.
snapshotReceipts
=
copyReceipts
(
w
.
current
.
receipts
)
w
.
snapshotState
=
w
.
current
.
state
.
Copy
()
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment