diff --git a/docker-compose.yml b/docker-compose.yml index d8441493..99e62346 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,6 +59,7 @@ services: DATABASE_PORT: 5432 DATABASE_USER: "vdbm" DATABASE_PASSWORD: "password" + ETH_CHAIN_ID: 4 ports: - "127.0.0.1:8081:8081" diff --git a/pkg/eth/api.go b/pkg/eth/api.go index 536673f3..879d6fd5 100644 --- a/pkg/eth/api.go +++ b/pkg/eth/api.go @@ -18,6 +18,7 @@ package eth import ( "context" + "database/sql" "encoding/json" "errors" "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. -func (api *PublicEthAPI) ChainId() (hexutil.Uint64, error) { +func (api *PublicEthAPI) ChainId() hexutil.Uint64 { chainID := new(big.Int) block, err := api.B.CurrentBlock() 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()) { 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 } } + if err == sql.ErrNoRows { + return code, nil + } + return nil, err } diff --git a/pkg/eth/backend.go b/pkg/eth/backend.go index 6d378fdd..214cc4e8 100644 --- a/pkg/eth/backend.go +++ b/pkg/eth/backend.go @@ -54,6 +54,7 @@ var ( ) const ( + RetrieveMaxBlockNumber = `SELECT max(block_number) FROM eth.header_cids` RetrieveCanonicalBlockHashByNumber = `SELECT block_hash FROM eth.header_cids INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key) 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 } +// 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 { CID string 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 func (b *Backend) GetCodeByNumberOrHash(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) ([]byte, error) { 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 { 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 -func (b *Backend) GetCodeByNumber(ctx context.Context, address common.Address, number uint64) ([]byte, error) { - hash, err := b.GetCanonicalHash(number) +func (b *Backend) GetCodeByNumber(ctx context.Context, address common.Address, number rpc.BlockNumber) ([]byte, error) { + 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 { return nil, err } diff --git a/test/integration_test.go b/test/integration_test.go index dea4fe37..f434110a 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -16,6 +16,9 @@ import ( "github.com/ethereum/go-ethereum/ethclient" ) +const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111" +const nonExistingAddress = "0x1111111111111111111111111111111111111111" + var _ = Describe("Integration test", func() { gethHttpPath := "http://127.0.0.1:8545" gethClient, err := ethclient.Dial(gethHttpPath) @@ -48,8 +51,6 @@ var _ = Describe("Integration test", func() { }) It("get not existing block by hash", func() { - nonExistingBlockHash := "0x111111111111111111111111111111111111111111111111111111111111111" - gethBlock, err := gethClient.BlockByHash(ctx, common.HexToHash(nonExistingBlockHash)) Expect(err).To(MatchError(ethereum.NotFound)) Expect(gethBlock).To(BeZero()) @@ -183,12 +184,25 @@ var _ = Describe("Integration test", func() { }) Describe("CodeAt", func() { - contractAddress := "0xdEE08501Ef5b68339ca920227d6520A10B72b65b" - It("Get code of deployed contract without block number", func() { - gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(contractAddress), nil) + contract, contractErr = integration.DeployContract() + + 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()) - 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(gethCode).To(Equal(ipldCode))