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
ad03d980
Commit
ad03d980
authored
Sep 26, 2019
by
Ryan Schneider
Committed by
Felix Lange
Sep 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
internal/ethapi: support block number or hash on state-related methods (#19491)
This change adds support for EIP-1898.
parent
62391ddb
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
408 additions
and
166 deletions
+408
-166
blockchain.go
core/blockchain.go
+5
-0
headerchain.go
core/headerchain.go
+4
-0
api_backend.go
eth/api_backend.go
+59
-0
graphql.go
graphql/graphql.go
+102
-146
api.go
internal/ethapi/api.go
+22
-20
backend.go
internal/ethapi/backend.go
+3
-0
api_backend.go
les/api_backend.go
+57
-0
lightchain.go
light/lightchain.go
+5
-0
types.go
rpc/types.go
+93
-0
types_test.go
rpc/types_test.go
+58
-0
No files found.
core/blockchain.go
View file @
ad03d980
...
@@ -2139,6 +2139,11 @@ func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
...
@@ -2139,6 +2139,11 @@ func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
return
bc
.
hc
.
HasHeader
(
hash
,
number
)
return
bc
.
hc
.
HasHeader
(
hash
,
number
)
}
}
// GetCanonicalHash returns the canonical hash for a given block number
func
(
bc
*
BlockChain
)
GetCanonicalHash
(
number
uint64
)
common
.
Hash
{
return
bc
.
hc
.
GetCanonicalHash
(
number
)
}
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
// hash, fetching towards the genesis block.
// hash, fetching towards the genesis block.
func
(
bc
*
BlockChain
)
GetBlockHashesFromHash
(
hash
common
.
Hash
,
max
uint64
)
[]
common
.
Hash
{
func
(
bc
*
BlockChain
)
GetBlockHashesFromHash
(
hash
common
.
Hash
,
max
uint64
)
[]
common
.
Hash
{
...
...
core/headerchain.go
View file @
ad03d980
...
@@ -448,6 +448,10 @@ func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
...
@@ -448,6 +448,10 @@ func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
return
hc
.
GetHeader
(
hash
,
number
)
return
hc
.
GetHeader
(
hash
,
number
)
}
}
func
(
hc
*
HeaderChain
)
GetCanonicalHash
(
number
uint64
)
common
.
Hash
{
return
rawdb
.
ReadCanonicalHash
(
hc
.
chainDb
,
number
)
}
// CurrentHeader retrieves the current head header of the canonical chain. The
// CurrentHeader retrieves the current head header of the canonical chain. The
// header is retrieved from the HeaderChain's internal cache.
// header is retrieved from the HeaderChain's internal cache.
func
(
hc
*
HeaderChain
)
CurrentHeader
()
*
types
.
Header
{
func
(
hc
*
HeaderChain
)
CurrentHeader
()
*
types
.
Header
{
...
...
eth/api_backend.go
View file @
ad03d980
...
@@ -72,6 +72,23 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
...
@@ -72,6 +72,23 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
return
b
.
eth
.
blockchain
.
GetHeaderByNumber
(
uint64
(
number
)),
nil
return
b
.
eth
.
blockchain
.
GetHeaderByNumber
(
uint64
(
number
)),
nil
}
}
func
(
b
*
EthAPIBackend
)
HeaderByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
types
.
Header
,
error
)
{
if
blockNr
,
ok
:=
blockNrOrHash
.
Number
();
ok
{
return
b
.
HeaderByNumber
(
ctx
,
blockNr
)
}
if
hash
,
ok
:=
blockNrOrHash
.
Hash
();
ok
{
header
:=
b
.
eth
.
blockchain
.
GetHeaderByHash
(
hash
)
if
header
==
nil
{
return
nil
,
errors
.
New
(
"header for hash not found"
)
}
if
blockNrOrHash
.
RequireCanonical
&&
b
.
eth
.
blockchain
.
GetCanonicalHash
(
header
.
Number
.
Uint64
())
!=
hash
{
return
nil
,
errors
.
New
(
"hash is not currently canonical"
)
}
return
header
,
nil
}
return
nil
,
errors
.
New
(
"invalid arguments; neither block nor hash specified"
)
}
func
(
b
*
EthAPIBackend
)
HeaderByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Header
,
error
)
{
func
(
b
*
EthAPIBackend
)
HeaderByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Header
,
error
)
{
return
b
.
eth
.
blockchain
.
GetHeaderByHash
(
hash
),
nil
return
b
.
eth
.
blockchain
.
GetHeaderByHash
(
hash
),
nil
}
}
...
@@ -93,6 +110,27 @@ func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ
...
@@ -93,6 +110,27 @@ func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ
return
b
.
eth
.
blockchain
.
GetBlockByHash
(
hash
),
nil
return
b
.
eth
.
blockchain
.
GetBlockByHash
(
hash
),
nil
}
}
func
(
b
*
EthAPIBackend
)
BlockByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
types
.
Block
,
error
)
{
if
blockNr
,
ok
:=
blockNrOrHash
.
Number
();
ok
{
return
b
.
BlockByNumber
(
ctx
,
blockNr
)
}
if
hash
,
ok
:=
blockNrOrHash
.
Hash
();
ok
{
header
:=
b
.
eth
.
blockchain
.
GetHeaderByHash
(
hash
)
if
header
==
nil
{
return
nil
,
errors
.
New
(
"header for hash not found"
)
}
if
blockNrOrHash
.
RequireCanonical
&&
b
.
eth
.
blockchain
.
GetCanonicalHash
(
header
.
Number
.
Uint64
())
!=
hash
{
return
nil
,
errors
.
New
(
"hash is not currently canonical"
)
}
block
:=
b
.
eth
.
blockchain
.
GetBlock
(
hash
,
header
.
Number
.
Uint64
())
if
block
==
nil
{
return
nil
,
errors
.
New
(
"header found, but block body is missing"
)
}
return
block
,
nil
}
return
nil
,
errors
.
New
(
"invalid arguments; neither block nor hash specified"
)
}
func
(
b
*
EthAPIBackend
)
StateAndHeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
{
func
(
b
*
EthAPIBackend
)
StateAndHeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
{
// Pending state is only known by the miner
// Pending state is only known by the miner
if
number
==
rpc
.
PendingBlockNumber
{
if
number
==
rpc
.
PendingBlockNumber
{
...
@@ -111,6 +149,27 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
...
@@ -111,6 +149,27 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
return
stateDb
,
header
,
err
return
stateDb
,
header
,
err
}
}
func
(
b
*
EthAPIBackend
)
StateAndHeaderByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
{
if
blockNr
,
ok
:=
blockNrOrHash
.
Number
();
ok
{
return
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
}
if
hash
,
ok
:=
blockNrOrHash
.
Hash
();
ok
{
header
,
err
:=
b
.
HeaderByHash
(
ctx
,
hash
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
if
header
==
nil
{
return
nil
,
nil
,
errors
.
New
(
"header for hash not found"
)
}
if
blockNrOrHash
.
RequireCanonical
&&
b
.
eth
.
blockchain
.
GetCanonicalHash
(
header
.
Number
.
Uint64
())
!=
hash
{
return
nil
,
nil
,
errors
.
New
(
"hash is not currently canonical"
)
}
stateDb
,
err
:=
b
.
eth
.
BlockChain
()
.
StateAt
(
header
.
Root
)
return
stateDb
,
header
,
err
}
return
nil
,
nil
,
errors
.
New
(
"invalid arguments; neither block nor hash specified"
)
}
func
(
b
*
EthAPIBackend
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
func
(
b
*
EthAPIBackend
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
return
b
.
eth
.
blockchain
.
GetReceiptsByHash
(
hash
),
nil
return
b
.
eth
.
blockchain
.
GetReceiptsByHash
(
hash
),
nil
}
}
...
...
graphql/graphql.go
View file @
ad03d980
This diff is collapsed.
Click to expand it.
internal/ethapi/api.go
View file @
ad03d980
...
@@ -530,8 +530,8 @@ func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 {
...
@@ -530,8 +530,8 @@ func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 {
// GetBalance returns the amount of wei for the given address in the state of the
// GetBalance returns the amount of wei for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.
// block numbers are also allowed.
func
(
s
*
PublicBlockChainAPI
)
GetBalance
(
ctx
context
.
Context
,
address
common
.
Address
,
blockNr
rpc
.
BlockNumber
)
(
*
hexutil
.
Big
,
error
)
{
func
(
s
*
PublicBlockChainAPI
)
GetBalance
(
ctx
context
.
Context
,
address
common
.
Address
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
)
(
*
hexutil
.
Big
,
error
)
{
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
OrHash
(
ctx
,
blockNrOrHash
)
if
state
==
nil
||
err
!=
nil
{
if
state
==
nil
||
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -555,8 +555,8 @@ type StorageResult struct {
...
@@ -555,8 +555,8 @@ type StorageResult struct {
}
}
// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
func
(
s
*
PublicBlockChainAPI
)
GetProof
(
ctx
context
.
Context
,
address
common
.
Address
,
storageKeys
[]
string
,
blockNr
rpc
.
BlockNumber
)
(
*
AccountResult
,
error
)
{
func
(
s
*
PublicBlockChainAPI
)
GetProof
(
ctx
context
.
Context
,
address
common
.
Address
,
storageKeys
[]
string
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
)
(
*
AccountResult
,
error
)
{
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
OrHash
(
ctx
,
blockNrOrHash
)
if
state
==
nil
||
err
!=
nil
{
if
state
==
nil
||
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -712,8 +712,8 @@ func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, bloc
...
@@ -712,8 +712,8 @@ func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, bloc
}
}
// GetCode returns the code stored at the given address in the state for the given block number.
// GetCode returns the code stored at the given address in the state for the given block number.
func
(
s
*
PublicBlockChainAPI
)
GetCode
(
ctx
context
.
Context
,
address
common
.
Address
,
blockNr
rpc
.
BlockNumber
)
(
hexutil
.
Bytes
,
error
)
{
func
(
s
*
PublicBlockChainAPI
)
GetCode
(
ctx
context
.
Context
,
address
common
.
Address
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
)
(
hexutil
.
Bytes
,
error
)
{
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
OrHash
(
ctx
,
blockNrOrHash
)
if
state
==
nil
||
err
!=
nil
{
if
state
==
nil
||
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -724,8 +724,8 @@ func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Addres
...
@@ -724,8 +724,8 @@ func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Addres
// GetStorageAt returns the storage from the state at the given address, key and
// GetStorageAt returns the storage from the state at the given address, key and
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// numbers are also allowed.
// numbers are also allowed.
func
(
s
*
PublicBlockChainAPI
)
GetStorageAt
(
ctx
context
.
Context
,
address
common
.
Address
,
key
string
,
blockNr
rpc
.
BlockNumber
)
(
hexutil
.
Bytes
,
error
)
{
func
(
s
*
PublicBlockChainAPI
)
GetStorageAt
(
ctx
context
.
Context
,
address
common
.
Address
,
key
string
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
)
(
hexutil
.
Bytes
,
error
)
{
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
OrHash
(
ctx
,
blockNrOrHash
)
if
state
==
nil
||
err
!=
nil
{
if
state
==
nil
||
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -757,10 +757,10 @@ type account struct {
...
@@ -757,10 +757,10 @@ type account struct {
StateDiff
*
map
[
common
.
Hash
]
common
.
Hash
`json:"stateDiff"`
StateDiff
*
map
[
common
.
Hash
]
common
.
Hash
`json:"stateDiff"`
}
}
func
DoCall
(
ctx
context
.
Context
,
b
Backend
,
args
CallArgs
,
blockNr
rpc
.
BlockNumber
,
overrides
map
[
common
.
Address
]
account
,
vmCfg
vm
.
Config
,
timeout
time
.
Duration
,
globalGasCap
*
big
.
Int
)
([]
byte
,
uint64
,
bool
,
error
)
{
func
DoCall
(
ctx
context
.
Context
,
b
Backend
,
args
CallArgs
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
,
overrides
map
[
common
.
Address
]
account
,
vmCfg
vm
.
Config
,
timeout
time
.
Duration
,
globalGasCap
*
big
.
Int
)
([]
byte
,
uint64
,
bool
,
error
)
{
defer
func
(
start
time
.
Time
)
{
log
.
Debug
(
"Executing EVM call finished"
,
"runtime"
,
time
.
Since
(
start
))
}(
time
.
Now
())
defer
func
(
start
time
.
Time
)
{
log
.
Debug
(
"Executing EVM call finished"
,
"runtime"
,
time
.
Since
(
start
))
}(
time
.
Now
())
state
,
header
,
err
:=
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
state
,
header
,
err
:=
b
.
StateAndHeaderByNumber
OrHash
(
ctx
,
blockNrOrHash
)
if
state
==
nil
||
err
!=
nil
{
if
state
==
nil
||
err
!=
nil
{
return
nil
,
0
,
false
,
err
return
nil
,
0
,
false
,
err
}
}
...
@@ -874,16 +874,16 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumb
...
@@ -874,16 +874,16 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumb
//
//
// Note, this function doesn't make and changes in the state/blockchain and is
// Note, this function doesn't make and changes in the state/blockchain and is
// useful to execute and retrieve values.
// useful to execute and retrieve values.
func
(
s
*
PublicBlockChainAPI
)
Call
(
ctx
context
.
Context
,
args
CallArgs
,
blockNr
rpc
.
BlockNumber
,
overrides
*
map
[
common
.
Address
]
account
)
(
hexutil
.
Bytes
,
error
)
{
func
(
s
*
PublicBlockChainAPI
)
Call
(
ctx
context
.
Context
,
args
CallArgs
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
,
overrides
*
map
[
common
.
Address
]
account
)
(
hexutil
.
Bytes
,
error
)
{
var
accounts
map
[
common
.
Address
]
account
var
accounts
map
[
common
.
Address
]
account
if
overrides
!=
nil
{
if
overrides
!=
nil
{
accounts
=
*
overrides
accounts
=
*
overrides
}
}
result
,
_
,
_
,
err
:=
DoCall
(
ctx
,
s
.
b
,
args
,
blockNr
,
accounts
,
vm
.
Config
{},
5
*
time
.
Second
,
s
.
b
.
RPCGasCap
())
result
,
_
,
_
,
err
:=
DoCall
(
ctx
,
s
.
b
,
args
,
blockNr
OrHash
,
accounts
,
vm
.
Config
{},
5
*
time
.
Second
,
s
.
b
.
RPCGasCap
())
return
(
hexutil
.
Bytes
)(
result
),
err
return
(
hexutil
.
Bytes
)(
result
),
err
}
}
func
DoEstimateGas
(
ctx
context
.
Context
,
b
Backend
,
args
CallArgs
,
blockNr
rpc
.
BlockNumber
,
gasCap
*
big
.
Int
)
(
hexutil
.
Uint64
,
error
)
{
func
DoEstimateGas
(
ctx
context
.
Context
,
b
Backend
,
args
CallArgs
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
,
gasCap
*
big
.
Int
)
(
hexutil
.
Uint64
,
error
)
{
// Binary search the gas requirement, as it may be higher than the amount used
// Binary search the gas requirement, as it may be higher than the amount used
var
(
var
(
lo
uint64
=
params
.
TxGas
-
1
lo
uint64
=
params
.
TxGas
-
1
...
@@ -894,7 +894,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
...
@@ -894,7 +894,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
hi
=
uint64
(
*
args
.
Gas
)
hi
=
uint64
(
*
args
.
Gas
)
}
else
{
}
else
{
// Retrieve the block to act as the gas ceiling
// Retrieve the block to act as the gas ceiling
block
,
err
:=
b
.
BlockByNumber
(
ctx
,
blockNr
)
block
,
err
:=
b
.
BlockByNumber
OrHash
(
ctx
,
blockNrOrHash
)
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
err
return
0
,
err
}
}
...
@@ -910,7 +910,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
...
@@ -910,7 +910,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
executable
:=
func
(
gas
uint64
)
bool
{
executable
:=
func
(
gas
uint64
)
bool
{
args
.
Gas
=
(
*
hexutil
.
Uint64
)(
&
gas
)
args
.
Gas
=
(
*
hexutil
.
Uint64
)(
&
gas
)
_
,
_
,
failed
,
err
:=
DoCall
(
ctx
,
b
,
args
,
rpc
.
PendingBlockNumber
,
nil
,
vm
.
Config
{},
0
,
gasCap
)
_
,
_
,
failed
,
err
:=
DoCall
(
ctx
,
b
,
args
,
blockNrOrHash
,
nil
,
vm
.
Config
{},
0
,
gasCap
)
if
err
!=
nil
||
failed
{
if
err
!=
nil
||
failed
{
return
false
return
false
}
}
...
@@ -937,7 +937,8 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
...
@@ -937,7 +937,8 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
// EstimateGas returns an estimate of the amount of gas needed to execute the
// EstimateGas returns an estimate of the amount of gas needed to execute the
// given transaction against the current pending block.
// given transaction against the current pending block.
func
(
s
*
PublicBlockChainAPI
)
EstimateGas
(
ctx
context
.
Context
,
args
CallArgs
)
(
hexutil
.
Uint64
,
error
)
{
func
(
s
*
PublicBlockChainAPI
)
EstimateGas
(
ctx
context
.
Context
,
args
CallArgs
)
(
hexutil
.
Uint64
,
error
)
{
return
DoEstimateGas
(
ctx
,
s
.
b
,
args
,
rpc
.
PendingBlockNumber
,
s
.
b
.
RPCGasCap
())
blockNrOrHash
:=
rpc
.
BlockNumberOrHashWithNumber
(
rpc
.
PendingBlockNumber
)
return
DoEstimateGas
(
ctx
,
s
.
b
,
args
,
blockNrOrHash
,
s
.
b
.
RPCGasCap
())
}
}
// ExecutionResult groups all structured logs emitted by the EVM
// ExecutionResult groups all structured logs emitted by the EVM
...
@@ -1224,9 +1225,9 @@ func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx cont
...
@@ -1224,9 +1225,9 @@ func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx cont
}
}
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
func
(
s
*
PublicTransactionPoolAPI
)
GetTransactionCount
(
ctx
context
.
Context
,
address
common
.
Address
,
blockNr
rpc
.
BlockNumber
)
(
*
hexutil
.
Uint64
,
error
)
{
func
(
s
*
PublicTransactionPoolAPI
)
GetTransactionCount
(
ctx
context
.
Context
,
address
common
.
Address
,
blockNr
OrHash
rpc
.
BlockNumberOrHash
)
(
*
hexutil
.
Uint64
,
error
)
{
// Ask transaction pool for the nonce which includes pending transactions
// Ask transaction pool for the nonce which includes pending transactions
if
blockNr
==
rpc
.
PendingBlockNumber
{
if
blockNr
,
ok
:=
blockNrOrHash
.
Number
();
ok
&&
blockNr
==
rpc
.
PendingBlockNumber
{
nonce
,
err
:=
s
.
b
.
GetPoolNonce
(
ctx
,
address
)
nonce
,
err
:=
s
.
b
.
GetPoolNonce
(
ctx
,
address
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -1234,7 +1235,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
...
@@ -1234,7 +1235,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
return
(
*
hexutil
.
Uint64
)(
&
nonce
),
nil
return
(
*
hexutil
.
Uint64
)(
&
nonce
),
nil
}
}
// Resolve block number and use its state to ask for the nonce
// Resolve block number and use its state to ask for the nonce
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
state
,
_
,
err
:=
s
.
b
.
StateAndHeaderByNumber
OrHash
(
ctx
,
blockNrOrHash
)
if
state
==
nil
||
err
!=
nil
{
if
state
==
nil
||
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -1405,7 +1406,8 @@ func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
...
@@ -1405,7 +1406,8 @@ func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
Value
:
args
.
Value
,
Value
:
args
.
Value
,
Data
:
input
,
Data
:
input
,
}
}
estimated
,
err
:=
DoEstimateGas
(
ctx
,
b
,
callArgs
,
rpc
.
PendingBlockNumber
,
b
.
RPCGasCap
())
pendingBlockNr
:=
rpc
.
BlockNumberOrHashWithNumber
(
rpc
.
PendingBlockNumber
)
estimated
,
err
:=
DoEstimateGas
(
ctx
,
b
,
callArgs
,
pendingBlockNr
,
b
.
RPCGasCap
())
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
...
internal/ethapi/backend.go
View file @
ad03d980
...
@@ -52,9 +52,12 @@ type Backend interface {
...
@@ -52,9 +52,12 @@ type Backend interface {
SetHead
(
number
uint64
)
SetHead
(
number
uint64
)
HeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
types
.
Header
,
error
)
HeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
types
.
Header
,
error
)
HeaderByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Header
,
error
)
HeaderByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Header
,
error
)
HeaderByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
types
.
Header
,
error
)
BlockByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
types
.
Block
,
error
)
BlockByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
types
.
Block
,
error
)
BlockByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Block
,
error
)
BlockByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Block
,
error
)
BlockByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
types
.
Block
,
error
)
StateAndHeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
StateAndHeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
StateAndHeaderByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
GetTd
(
hash
common
.
Hash
)
*
big
.
Int
GetTd
(
hash
common
.
Hash
)
*
big
.
Int
GetEVM
(
ctx
context
.
Context
,
msg
core
.
Message
,
state
*
state
.
StateDB
,
header
*
types
.
Header
)
(
*
vm
.
EVM
,
func
()
error
,
error
)
GetEVM
(
ctx
context
.
Context
,
msg
core
.
Message
,
state
*
state
.
StateDB
,
header
*
types
.
Header
)
(
*
vm
.
EVM
,
func
()
error
,
error
)
...
...
les/api_backend.go
View file @
ad03d980
...
@@ -65,6 +65,26 @@ func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
...
@@ -65,6 +65,26 @@ func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
return
b
.
eth
.
blockchain
.
GetHeaderByNumberOdr
(
ctx
,
uint64
(
number
))
return
b
.
eth
.
blockchain
.
GetHeaderByNumberOdr
(
ctx
,
uint64
(
number
))
}
}
func
(
b
*
LesApiBackend
)
HeaderByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
types
.
Header
,
error
)
{
if
blockNr
,
ok
:=
blockNrOrHash
.
Number
();
ok
{
return
b
.
HeaderByNumber
(
ctx
,
blockNr
)
}
if
hash
,
ok
:=
blockNrOrHash
.
Hash
();
ok
{
header
,
err
:=
b
.
HeaderByHash
(
ctx
,
hash
)
if
err
!=
nil
{
return
nil
,
err
}
if
header
==
nil
{
return
nil
,
errors
.
New
(
"header for hash not found"
)
}
if
blockNrOrHash
.
RequireCanonical
&&
b
.
eth
.
blockchain
.
GetCanonicalHash
(
header
.
Number
.
Uint64
())
!=
hash
{
return
nil
,
errors
.
New
(
"hash is not currently canonical"
)
}
return
header
,
nil
}
return
nil
,
errors
.
New
(
"invalid arguments; neither block nor hash specified"
)
}
func
(
b
*
LesApiBackend
)
HeaderByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Header
,
error
)
{
func
(
b
*
LesApiBackend
)
HeaderByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Header
,
error
)
{
return
b
.
eth
.
blockchain
.
GetHeaderByHash
(
hash
),
nil
return
b
.
eth
.
blockchain
.
GetHeaderByHash
(
hash
),
nil
}
}
...
@@ -81,6 +101,26 @@ func (b *LesApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ
...
@@ -81,6 +101,26 @@ func (b *LesApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ
return
b
.
eth
.
blockchain
.
GetBlockByHash
(
ctx
,
hash
)
return
b
.
eth
.
blockchain
.
GetBlockByHash
(
ctx
,
hash
)
}
}
func
(
b
*
LesApiBackend
)
BlockByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
types
.
Block
,
error
)
{
if
blockNr
,
ok
:=
blockNrOrHash
.
Number
();
ok
{
return
b
.
BlockByNumber
(
ctx
,
blockNr
)
}
if
hash
,
ok
:=
blockNrOrHash
.
Hash
();
ok
{
block
,
err
:=
b
.
BlockByHash
(
ctx
,
hash
)
if
err
!=
nil
{
return
nil
,
err
}
if
block
==
nil
{
return
nil
,
errors
.
New
(
"header found, but block body is missing"
)
}
if
blockNrOrHash
.
RequireCanonical
&&
b
.
eth
.
blockchain
.
GetCanonicalHash
(
block
.
NumberU64
())
!=
hash
{
return
nil
,
errors
.
New
(
"hash is not currently canonical"
)
}
return
block
,
nil
}
return
nil
,
errors
.
New
(
"invalid arguments; neither block nor hash specified"
)
}
func
(
b
*
LesApiBackend
)
StateAndHeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
{
func
(
b
*
LesApiBackend
)
StateAndHeaderByNumber
(
ctx
context
.
Context
,
number
rpc
.
BlockNumber
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
{
header
,
err
:=
b
.
HeaderByNumber
(
ctx
,
number
)
header
,
err
:=
b
.
HeaderByNumber
(
ctx
,
number
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -92,6 +132,23 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
...
@@ -92,6 +132,23 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
return
light
.
NewState
(
ctx
,
header
,
b
.
eth
.
odr
),
header
,
nil
return
light
.
NewState
(
ctx
,
header
,
b
.
eth
.
odr
),
header
,
nil
}
}
func
(
b
*
LesApiBackend
)
StateAndHeaderByNumberOrHash
(
ctx
context
.
Context
,
blockNrOrHash
rpc
.
BlockNumberOrHash
)
(
*
state
.
StateDB
,
*
types
.
Header
,
error
)
{
if
blockNr
,
ok
:=
blockNrOrHash
.
Number
();
ok
{
return
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
}
if
hash
,
ok
:=
blockNrOrHash
.
Hash
();
ok
{
header
:=
b
.
eth
.
blockchain
.
GetHeaderByHash
(
hash
)
if
header
==
nil
{
return
nil
,
nil
,
errors
.
New
(
"header for hash not found"
)
}
if
blockNrOrHash
.
RequireCanonical
&&
b
.
eth
.
blockchain
.
GetCanonicalHash
(
header
.
Number
.
Uint64
())
!=
hash
{
return
nil
,
nil
,
errors
.
New
(
"hash is not currently canonical"
)
}
return
light
.
NewState
(
ctx
,
header
,
b
.
eth
.
odr
),
header
,
nil
}
return
nil
,
nil
,
errors
.
New
(
"invalid arguments; neither block nor hash specified"
)
}
func
(
b
*
LesApiBackend
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
func
(
b
*
LesApiBackend
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
b
.
eth
.
chainDb
,
hash
);
number
!=
nil
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
b
.
eth
.
chainDb
,
hash
);
number
!=
nil
{
return
light
.
GetBlockReceipts
(
ctx
,
b
.
eth
.
odr
,
hash
,
*
number
)
return
light
.
GetBlockReceipts
(
ctx
,
b
.
eth
.
odr
,
hash
,
*
number
)
...
...
light/lightchain.go
View file @
ad03d980
...
@@ -426,6 +426,11 @@ func (lc *LightChain) HasHeader(hash common.Hash, number uint64) bool {
...
@@ -426,6 +426,11 @@ func (lc *LightChain) HasHeader(hash common.Hash, number uint64) bool {
return
lc
.
hc
.
HasHeader
(
hash
,
number
)
return
lc
.
hc
.
HasHeader
(
hash
,
number
)
}
}
// GetCanonicalHash returns the canonical hash for a given block number
func
(
bc
*
LightChain
)
GetCanonicalHash
(
number
uint64
)
common
.
Hash
{
return
bc
.
hc
.
GetCanonicalHash
(
number
)
}
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
// hash, fetching towards the genesis block.
// hash, fetching towards the genesis block.
func
(
lc
*
LightChain
)
GetBlockHashesFromHash
(
hash
common
.
Hash
,
max
uint64
)
[]
common
.
Hash
{
func
(
lc
*
LightChain
)
GetBlockHashesFromHash
(
hash
common
.
Hash
,
max
uint64
)
[]
common
.
Hash
{
...
...
rpc/types.go
View file @
ad03d980
...
@@ -18,10 +18,12 @@ package rpc
...
@@ -18,10 +18,12 @@ package rpc
import
(
import
(
"context"
"context"
"encoding/json"
"fmt"
"fmt"
"math"
"math"
"strings"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
)
)
...
@@ -105,3 +107,94 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
...
@@ -105,3 +107,94 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
func
(
bn
BlockNumber
)
Int64
()
int64
{
func
(
bn
BlockNumber
)
Int64
()
int64
{
return
(
int64
)(
bn
)
return
(
int64
)(
bn
)
}
}
type
BlockNumberOrHash
struct
{
BlockNumber
*
BlockNumber
`json:"blockNumber,omitempty"`
BlockHash
*
common
.
Hash
`json:"blockHash,omitempty"`
RequireCanonical
bool
`json:"requireCanonical,omitempty"`
}
func
(
bnh
*
BlockNumberOrHash
)
UnmarshalJSON
(
data
[]
byte
)
error
{
type
erased
BlockNumberOrHash
e
:=
erased
{}
err
:=
json
.
Unmarshal
(
data
,
&
e
)
if
err
==
nil
{
if
e
.
BlockNumber
!=
nil
&&
e
.
BlockHash
!=
nil
{
return
fmt
.
Errorf
(
"cannot specify both BlockHash and BlockNumber, choose one or the other"
)
}
bnh
.
BlockNumber
=
e
.
BlockNumber
bnh
.
BlockHash
=
e
.
BlockHash
bnh
.
RequireCanonical
=
e
.
RequireCanonical
return
nil
}
var
input
string
err
=
json
.
Unmarshal
(
data
,
&
input
)
if
err
!=
nil
{
return
err
}
switch
input
{
case
"earliest"
:
bn
:=
EarliestBlockNumber
bnh
.
BlockNumber
=
&
bn
return
nil
case
"latest"
:
bn
:=
LatestBlockNumber
bnh
.
BlockNumber
=
&
bn
return
nil
case
"pending"
:
bn
:=
PendingBlockNumber
bnh
.
BlockNumber
=
&
bn
return
nil
default
:
if
len
(
input
)
==
66
{
hash
:=
common
.
Hash
{}
err
:=
hash
.
UnmarshalText
([]
byte
(
input
))
if
err
!=
nil
{
return
err
}
bnh
.
BlockHash
=
&
hash
return
nil
}
else
{
blckNum
,
err
:=
hexutil
.
DecodeUint64
(
input
)
if
err
!=
nil
{
return
err
}
if
blckNum
>
math
.
MaxInt64
{
return
fmt
.
Errorf
(
"blocknumber too high"
)
}
bn
:=
BlockNumber
(
blckNum
)
bnh
.
BlockNumber
=
&
bn
return
nil
}
}
}
func
(
bnh
*
BlockNumberOrHash
)
Number
()
(
BlockNumber
,
bool
)
{
if
bnh
.
BlockNumber
!=
nil
{
return
*
bnh
.
BlockNumber
,
true
}
return
BlockNumber
(
0
),
false
}
func
(
bnh
*
BlockNumberOrHash
)
Hash
()
(
common
.
Hash
,
bool
)
{
if
bnh
.
BlockHash
!=
nil
{
return
*
bnh
.
BlockHash
,
true
}
return
common
.
Hash
{},
false
}
func
BlockNumberOrHashWithNumber
(
blockNr
BlockNumber
)
BlockNumberOrHash
{
return
BlockNumberOrHash
{
BlockNumber
:
&
blockNr
,
BlockHash
:
nil
,
RequireCanonical
:
false
,
}
}
func
BlockNumberOrHashWithHash
(
hash
common
.
Hash
,
canonical
bool
)
BlockNumberOrHash
{
return
BlockNumberOrHash
{
BlockNumber
:
nil
,
BlockHash
:
&
hash
,
RequireCanonical
:
canonical
,
}
}
rpc/types_test.go
View file @
ad03d980
...
@@ -20,6 +20,7 @@ import (
...
@@ -20,6 +20,7 @@ import (
"encoding/json"
"encoding/json"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/common/math"
)
)
...
@@ -64,3 +65,60 @@ func TestBlockNumberJSONUnmarshal(t *testing.T) {
...
@@ -64,3 +65,60 @@ func TestBlockNumberJSONUnmarshal(t *testing.T) {
}
}
}
}
}
}
func
TestBlockNumberOrHash_UnmarshalJSON
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
input
string
mustFail
bool
expected
BlockNumberOrHash
}{
0
:
{
`"0x"`
,
true
,
BlockNumberOrHash
{}},
1
:
{
`"0x0"`
,
false
,
BlockNumberOrHashWithNumber
(
0
)},
2
:
{
`"0X1"`
,
false
,
BlockNumberOrHashWithNumber
(
1
)},
3
:
{
`"0x00"`
,
true
,
BlockNumberOrHash
{}},
4
:
{
`"0x01"`
,
true
,
BlockNumberOrHash
{}},
5
:
{
`"0x1"`
,
false
,
BlockNumberOrHashWithNumber
(
1
)},
6
:
{
`"0x12"`
,
false
,
BlockNumberOrHashWithNumber
(
18
)},
7
:
{
`"0x7fffffffffffffff"`
,
false
,
BlockNumberOrHashWithNumber
(
math
.
MaxInt64
)},
8
:
{
`"0x8000000000000000"`
,
true
,
BlockNumberOrHash
{}},
9
:
{
"0"
,
true
,
BlockNumberOrHash
{}},
10
:
{
`"ff"`
,
true
,
BlockNumberOrHash
{}},
11
:
{
`"pending"`
,
false
,
BlockNumberOrHashWithNumber
(
PendingBlockNumber
)},
12
:
{
`"latest"`
,
false
,
BlockNumberOrHashWithNumber
(
LatestBlockNumber
)},
13
:
{
`"earliest"`
,
false
,
BlockNumberOrHashWithNumber
(
EarliestBlockNumber
)},
14
:
{
`someString`
,
true
,
BlockNumberOrHash
{}},
15
:
{
`""`
,
true
,
BlockNumberOrHash
{}},
16
:
{
``
,
true
,
BlockNumberOrHash
{}},
17
:
{
`"0x0000000000000000000000000000000000000000000000000000000000000000"`
,
false
,
BlockNumberOrHashWithHash
(
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000000"
),
false
)},
18
:
{
`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}`
,
false
,
BlockNumberOrHashWithHash
(
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000000"
),
false
)},
19
:
{
`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","requireCanonical":false}`
,
false
,
BlockNumberOrHashWithHash
(
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000000"
),
false
)},
20
:
{
`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","requireCanonical":true}`
,
false
,
BlockNumberOrHashWithHash
(
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000000"
),
true
)},
21
:
{
`{"blockNumber":"0x1"}`
,
false
,
BlockNumberOrHashWithNumber
(
1
)},
22
:
{
`{"blockNumber":"pending"}`
,
false
,
BlockNumberOrHashWithNumber
(
PendingBlockNumber
)},
23
:
{
`{"blockNumber":"latest"}`
,
false
,
BlockNumberOrHashWithNumber
(
LatestBlockNumber
)},
24
:
{
`{"blockNumber":"earliest"}`
,
false
,
BlockNumberOrHashWithNumber
(
EarliestBlockNumber
)},
25
:
{
`{"blockNumber":"0x1", "blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}`
,
true
,
BlockNumberOrHash
{}},
}
for
i
,
test
:=
range
tests
{
var
bnh
BlockNumberOrHash
err
:=
json
.
Unmarshal
([]
byte
(
test
.
input
),
&
bnh
)
if
test
.
mustFail
&&
err
==
nil
{
t
.
Errorf
(
"Test %d should fail"
,
i
)
continue
}
if
!
test
.
mustFail
&&
err
!=
nil
{
t
.
Errorf
(
"Test %d should pass but got err: %v"
,
i
,
err
)
continue
}
hash
,
hashOk
:=
bnh
.
Hash
()
expectedHash
,
expectedHashOk
:=
test
.
expected
.
Hash
()
num
,
numOk
:=
bnh
.
Number
()
expectedNum
,
expectedNumOk
:=
test
.
expected
.
Number
()
if
bnh
.
RequireCanonical
!=
test
.
expected
.
RequireCanonical
||
hash
!=
expectedHash
||
hashOk
!=
expectedHashOk
||
num
!=
expectedNum
||
numOk
!=
expectedNumOk
{
t
.
Errorf
(
"Test %d got unexpected value, want %v, got %v"
,
i
,
test
.
expected
,
bnh
)
}
}
}
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