fix CodeAt without block number

This commit is contained in:
ramil 2021-04-21 14:16:47 +03:00
parent f8b9d9475e
commit 9b960a105f
4 changed files with 53 additions and 12 deletions

View File

@ -59,6 +59,7 @@ services:
DATABASE_PORT: 5432 DATABASE_PORT: 5432
DATABASE_USER: "vdbm" DATABASE_USER: "vdbm"
DATABASE_PASSWORD: "password" DATABASE_PASSWORD: "password"
ETH_CHAIN_ID: 4
ports: ports:
- "127.0.0.1:8081:8081" - "127.0.0.1:8081:8081"

View File

@ -18,6 +18,7 @@ package eth
import ( import (
"context" "context"
"database/sql"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -168,16 +169,18 @@ func (pea *PublicEthAPI) GetBlockByHash(ctx context.Context, hash common.Hash, f
} }
// ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config.
func (api *PublicEthAPI) ChainId() (hexutil.Uint64, error) { func (api *PublicEthAPI) ChainId() hexutil.Uint64 {
chainID := new(big.Int) chainID := new(big.Int)
block, err := api.B.CurrentBlock() block, err := api.B.CurrentBlock()
if err != nil { if err != nil {
return 0, err logrus.Errorf("ChainId failed with err %s", err.Error())
return 0
} }
if config := api.B.Config.ChainConfig; config.IsEIP155(block.Number()) { if config := api.B.Config.ChainConfig; config.IsEIP155(block.Number()) {
chainID = config.ChainID chainID = config.ChainID
} }
return (hexutil.Uint64)(chainID.Uint64()), nil return (hexutil.Uint64)(chainID.Uint64())
} }
/* /*
@ -682,6 +685,10 @@ func (pea *PublicEthAPI) GetCode(ctx context.Context, address common.Address, bl
return res, nil return res, nil
} }
} }
if err == sql.ErrNoRows {
return code, nil
}
return nil, err return nil, err
} }

View File

@ -54,6 +54,7 @@ var (
) )
const ( const (
RetrieveMaxBlockNumber = `SELECT max(block_number) FROM eth.header_cids`
RetrieveCanonicalBlockHashByNumber = `SELECT block_hash FROM eth.header_cids RetrieveCanonicalBlockHashByNumber = `SELECT block_hash FROM eth.header_cids
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key) INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
WHERE id = (SELECT canonical_header_id($1))` WHERE id = (SELECT canonical_header_id($1))`
@ -548,6 +549,15 @@ func (b *Backend) GetCanonicalHash(number uint64) (common.Hash, error) {
return common.HexToHash(hashResult), nil return common.HexToHash(hashResult), nil
} }
// GetLastBlockNumber gets the latest block number
func (b *Backend) GetLastBlockNumber() (uint64, error) {
var number uint64
if err := b.DB.Get(&number, RetrieveMaxBlockNumber); err != nil {
return 0, err
}
return number, nil
}
type rowResult struct { type rowResult struct {
CID string CID string
Data []byte Data []byte
@ -603,7 +613,7 @@ func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address,
// GetCodeByNumberOrHash returns the byte code for the contract deployed at the provided address at the block with the provided hash or block number // GetCodeByNumberOrHash returns the byte code for the contract deployed at the provided address at the block with the provided hash or block number
func (b *Backend) GetCodeByNumberOrHash(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) ([]byte, error) { func (b *Backend) GetCodeByNumberOrHash(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) ([]byte, error) {
if blockNr, ok := blockNrOrHash.Number(); ok { if blockNr, ok := blockNrOrHash.Number(); ok {
return b.GetCodeByNumber(ctx, address, uint64(blockNr.Int64())) return b.GetCodeByNumber(ctx, address, blockNr)
} }
if hash, ok := blockNrOrHash.Hash(); ok { if hash, ok := blockNrOrHash.Hash(); ok {
return b.GetCodeByHash(ctx, address, hash) return b.GetCodeByHash(ctx, address, hash)
@ -612,8 +622,17 @@ func (b *Backend) GetCodeByNumberOrHash(ctx context.Context, address common.Addr
} }
// GetCodeByNumber returns the byte code for the contract deployed at the provided address at the canonical block with the provided block number // GetCodeByNumber returns the byte code for the contract deployed at the provided address at the canonical block with the provided block number
func (b *Backend) GetCodeByNumber(ctx context.Context, address common.Address, number uint64) ([]byte, error) { func (b *Backend) GetCodeByNumber(ctx context.Context, address common.Address, number rpc.BlockNumber) ([]byte, error) {
hash, err := b.GetCanonicalHash(number) if number == rpc.LatestBlockNumber {
// get latest block number
latestBlockNumber, err := b.GetLastBlockNumber()
if err != nil {
return nil, err
}
number = rpc.BlockNumber(latestBlockNumber)
}
hash, err := b.GetCanonicalHash(uint64(number.Int64()))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -16,6 +16,9 @@ import (
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
) )
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
const nonExistingAddress = "0x1111111111111111111111111111111111111111"
var _ = Describe("Integration test", func() { var _ = Describe("Integration test", func() {
gethHttpPath := "http://127.0.0.1:8545" gethHttpPath := "http://127.0.0.1:8545"
gethClient, err := ethclient.Dial(gethHttpPath) gethClient, err := ethclient.Dial(gethHttpPath)
@ -48,8 +51,6 @@ var _ = Describe("Integration test", func() {
}) })
It("get not existing block by hash", func() { It("get not existing block by hash", func() {
nonExistingBlockHash := "0x111111111111111111111111111111111111111111111111111111111111111"
gethBlock, err := gethClient.BlockByHash(ctx, common.HexToHash(nonExistingBlockHash)) gethBlock, err := gethClient.BlockByHash(ctx, common.HexToHash(nonExistingBlockHash))
Expect(err).To(MatchError(ethereum.NotFound)) Expect(err).To(MatchError(ethereum.NotFound))
Expect(gethBlock).To(BeZero()) Expect(gethBlock).To(BeZero())
@ -183,12 +184,25 @@ var _ = Describe("Integration test", func() {
}) })
Describe("CodeAt", func() { Describe("CodeAt", func() {
contractAddress := "0xdEE08501Ef5b68339ca920227d6520A10B72b65b" contract, contractErr = integration.DeployContract()
It("Get code of deployed contract without block number", func() {
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(contractAddress), nil) It("gets code at non-existing address without block number", func() {
Expect(contractErr).ToNot(HaveOccurred())
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contractAddress), nil) ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
Expect(err).ToNot(HaveOccurred())
Expect(gethCode).To(BeEmpty())
Expect(gethCode).To(Equal(ipldCode))
})
It("gets code of deployed contract without block number", func() {
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(contract.Address), nil)
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), nil)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(gethCode).To(Equal(ipldCode)) Expect(gethCode).To(Equal(ipldCode))