|
|
@@ -19,20 +19,23 @@ package light
|
|
|
import (
|
|
|
"bytes"
|
|
|
"context"
|
|
|
+ "errors"
|
|
|
"math/big"
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
"github.com/ethereum/go-ethereum/core"
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
- "github.com/ethereum/go-ethereum/crypto"
|
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
|
)
|
|
|
|
|
|
-var sha3Nil = crypto.Keccak256Hash(nil)
|
|
|
+// errNonCanonicalHash is returned if the requested chain data doesn't belong
|
|
|
+// to the canonical chain. ODR can only retrieve the canonical chain data covered
|
|
|
+// by the CHT or Bloom trie for verification.
|
|
|
+var errNonCanonicalHash = errors.New("hash is not currently canonical")
|
|
|
|
|
|
// GetHeaderByNumber retrieves the canonical block header corresponding to the
|
|
|
-// given number.
|
|
|
+// given number. The returned header is proven by local CHT.
|
|
|
func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*types.Header, error) {
|
|
|
// Try to find it in the local database first.
|
|
|
db := odr.Database()
|
|
|
@@ -63,25 +66,6 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ
|
|
|
return r.Header, nil
|
|
|
}
|
|
|
|
|
|
-// GetUntrustedHeaderByNumber retrieves specified block header without
|
|
|
-// correctness checking. Note this function should only be used in light
|
|
|
-// client checkpoint syncing.
|
|
|
-func GetUntrustedHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64, peerId string) (*types.Header, error) {
|
|
|
- // todo(rjl493456442) it's a hack to retrieve headers which is not covered
|
|
|
- // by CHT. Fix it in LES4
|
|
|
- r := &ChtRequest{
|
|
|
- BlockNum: number,
|
|
|
- ChtNum: number / odr.IndexerConfig().ChtSize,
|
|
|
- Untrusted: true,
|
|
|
- PeerId: peerId,
|
|
|
- Config: odr.IndexerConfig(),
|
|
|
- }
|
|
|
- if err := odr.Retrieve(ctx, r); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return r.Header, nil
|
|
|
-}
|
|
|
-
|
|
|
// GetCanonicalHash retrieves the canonical block hash corresponding to the number.
|
|
|
func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) {
|
|
|
hash := rawdb.ReadCanonicalHash(odr.Database(), number)
|
|
|
@@ -102,10 +86,13 @@ func GetTd(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64)
|
|
|
if td != nil {
|
|
|
return td, nil
|
|
|
}
|
|
|
- _, err := GetHeaderByNumber(ctx, odr, number)
|
|
|
+ header, err := GetHeaderByNumber(ctx, odr, number)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
+ if header.Hash() != hash {
|
|
|
+ return nil, errNonCanonicalHash
|
|
|
+ }
|
|
|
// <hash, number> -> td mapping already be stored in db, get it.
|
|
|
return rawdb.ReadTd(odr.Database(), hash, number), nil
|
|
|
}
|
|
|
@@ -120,6 +107,9 @@ func GetBodyRLP(ctx context.Context, odr OdrBackend, hash common.Hash, number ui
|
|
|
if err != nil {
|
|
|
return nil, errNoHeader
|
|
|
}
|
|
|
+ if header.Hash() != hash {
|
|
|
+ return nil, errNonCanonicalHash
|
|
|
+ }
|
|
|
r := &BlockRequest{Hash: hash, Number: number, Header: header}
|
|
|
if err := odr.Retrieve(ctx, r); err != nil {
|
|
|
return nil, err
|
|
|
@@ -167,6 +157,9 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
|
|
|
if err != nil {
|
|
|
return nil, errNoHeader
|
|
|
}
|
|
|
+ if header.Hash() != hash {
|
|
|
+ return nil, errNonCanonicalHash
|
|
|
+ }
|
|
|
r := &ReceiptsRequest{Hash: hash, Number: number, Header: header}
|
|
|
if err := odr.Retrieve(ctx, r); err != nil {
|
|
|
return nil, err
|