fix encoding when storage is empty #94
@ -1,4 +1,20 @@
|
|||||||
-- +goose Up
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
-- returns if a state leaf node was removed within the provided block number
|
||||||
|
CREATE OR REPLACE FUNCTION was_state_leaf_removed(key character varying, hash character varying)
|
||||||
|
RETURNS boolean AS $$
|
||||||
|
SELECT state_cids.node_type = 3
|
||||||
|
FROM eth.state_cids
|
||||||
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
WHERE state_leaf_key = key
|
||||||
|
AND block_number <= (SELECT block_number
|
||||||
|
FROM eth.header_cids
|
||||||
|
WHERE block_hash = hash)
|
||||||
|
ORDER BY block_number DESC LIMIT 1;
|
||||||
|
$$
|
||||||
|
language sql;
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
-- +goose StatementBegin
|
-- +goose StatementBegin
|
||||||
CREATE TYPE child_result AS (
|
CREATE TYPE child_result AS (
|
||||||
has_child BOOLEAN,
|
has_child BOOLEAN,
|
||||||
@ -115,6 +131,7 @@ LANGUAGE 'plpgsql';
|
|||||||
-- +goose StatementEnd
|
-- +goose StatementEnd
|
||||||
|
|
||||||
-- +goose Down
|
-- +goose Down
|
||||||
|
DROP FUNCTION was_state_leaf_removed;
|
||||||
DROP FUNCTION canonical_header_id;
|
DROP FUNCTION canonical_header_id;
|
||||||
DROP FUNCTION canonical_header_from_array;
|
DROP FUNCTION canonical_header_from_array;
|
||||||
DROP FUNCTION has_child;
|
DROP FUNCTION has_child;
|
||||||
|
@ -20,7 +20,7 @@ services:
|
|||||||
restart: on-failure
|
restart: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
image: vulcanize/statediff-migrations:v0.7.0
|
image: vulcanize/statediff-migrations:v0.8.0
|
||||||
environment:
|
environment:
|
||||||
DATABASE_USER: vdbm
|
DATABASE_USER: vdbm
|
||||||
DATABASE_NAME: vulcanize_public
|
DATABASE_NAME: vulcanize_public
|
||||||
@ -39,6 +39,7 @@ services:
|
|||||||
- vdb_db_eth_server:/var/lib/postgresql/data
|
- vdb_db_eth_server:/var/lib/postgresql/data
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8077:5432"
|
- "127.0.0.1:8077:5432"
|
||||||
|
command: ["postgres", "-c", "log_statement=all"]
|
||||||
|
|
||||||
eth-server:
|
eth-server:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -61,6 +62,7 @@ services:
|
|||||||
DATABASE_USER: "vdbm"
|
DATABASE_USER: "vdbm"
|
||||||
DATABASE_PASSWORD: "password"
|
DATABASE_PASSWORD: "password"
|
||||||
ETH_CHAIN_ID: 4
|
ETH_CHAIN_ID: 4
|
||||||
|
RUN_DB_MIGRATION: "no"
|
||||||
volumes:
|
volumes:
|
||||||
- type: bind
|
- type: bind
|
||||||
source: ./chain.json
|
source: ./chain.json
|
||||||
|
@ -4,18 +4,21 @@
|
|||||||
# Construct the connection string for postgres
|
# Construct the connection string for postgres
|
||||||
VDB_PG_CONNECT=postgresql://$DATABASE_USER:$DATABASE_PASSWORD@$DATABASE_HOSTNAME:$DATABASE_PORT/$DATABASE_NAME?sslmode=disable
|
VDB_PG_CONNECT=postgresql://$DATABASE_USER:$DATABASE_PASSWORD@$DATABASE_HOSTNAME:$DATABASE_PORT/$DATABASE_NAME?sslmode=disable
|
||||||
|
|
||||||
# Run the DB migrations
|
|
||||||
echo "Connecting with: $VDB_PG_CONNECT"
|
|
||||||
echo "Running database migrations"
|
|
||||||
./goose -dir migrations/vulcanizedb postgres "$VDB_PG_CONNECT" up
|
|
||||||
rv=$?
|
|
||||||
|
|
||||||
if [ $rv != 0 ]; then
|
if [ "$RUN_DB_MIGRATION" != "no" ]
|
||||||
echo "Could not run migrations. Are the database details correct?"
|
then
|
||||||
exit 1
|
# Run the DB migrations
|
||||||
|
echo "Connecting with: $VDB_PG_CONNECT"
|
||||||
|
echo "Running database migrations"
|
||||||
|
./goose -dir migrations/vulcanizedb postgres "$VDB_PG_CONNECT" up
|
||||||
|
rv=$?
|
||||||
|
|
||||||
|
if [ $rv != 0 ]; then
|
||||||
|
echo "Could not run migrations. Are the database details correct?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
echo "Beginning the ipld-eth-server process"
|
echo "Beginning the ipld-eth-server process"
|
||||||
|
|
||||||
echo running: ./ipld-eth-server ${VDB_COMMAND} --config=config.toml
|
echo running: ./ipld-eth-server ${VDB_COMMAND} --config=config.toml
|
||||||
|
@ -476,16 +476,16 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
It("Returns empty slice if it tries to access a contract which does not exist", func() {
|
It("Returns empty slice if it tries to access a contract which does not exist", func() {
|
||||||
storage, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(0))
|
storage, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(storage).To(Equal(hexutil.Bytes(make([]byte, 32))))
|
Expect(storage).To(Equal(hexutil.Bytes(eth.EmptyNodeValue)))
|
||||||
|
|
||||||
storage, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(1))
|
storage, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(storage).To(Equal(hexutil.Bytes(make([]byte, 32))))
|
Expect(storage).To(Equal(hexutil.Bytes(eth.EmptyNodeValue)))
|
||||||
})
|
})
|
||||||
It("Returns empty slice if it tries to access a contract slot which does not exist", func() {
|
It("Returns empty slice if it tries to access a contract slot which does not exist", func() {
|
||||||
storage, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, randomHash.Hex(), rpc.BlockNumberOrHashWithNumber(2))
|
storage, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, randomHash.Hex(), rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(storage).To(Equal(hexutil.Bytes(make([]byte, 32))))
|
Expect(storage).To(Equal(hexutil.Bytes(eth.EmptyNodeValue)))
|
||||||
})
|
})
|
||||||
It("Retrieves the storage value at the provided contract address and storage leaf key at the block with the provided hash or number", func() {
|
It("Retrieves the storage value at the provided contract address and storage leaf key at the block with the provided hash or number", func() {
|
||||||
// After deployment
|
// After deployment
|
||||||
@ -506,7 +506,7 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
|
|
||||||
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithNumber(5))
|
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(val).To(Equal(hexutil.Bytes{}))
|
Expect(val).To(Equal(hexutil.Bytes(eth.EmptyNodeValue)))
|
||||||
})
|
})
|
||||||
It("Throws an error for a non-existing block hash", func() {
|
It("Throws an error for a non-existing block hash", func() {
|
||||||
_, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithHash(randomHash, true))
|
_, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithHash(randomHash, true))
|
||||||
|
@ -127,7 +127,7 @@ const (
|
|||||||
AND block_number <= $2
|
AND block_number <= $2
|
||||||
ORDER BY block_number DESC
|
ORDER BY block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr = `SELECT storage_cids.cid, data, storage_cids.node_type
|
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr = `SELECT storage_cids.cid, data, storage_cids.node_type, was_state_leaf_removed($1, $3) AS state_leaf_removed
|
||||||
FROM eth.storage_cids
|
FROM eth.storage_cids
|
||||||
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
||||||
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
@ -137,7 +137,7 @@ const (
|
|||||||
AND block_number <= $3
|
AND block_number <= $3
|
||||||
ORDER BY block_number DESC
|
ORDER BY block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT storage_cids.cid, data, storage_cids.node_type
|
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT storage_cids.cid, data, storage_cids.node_type, was_state_leaf_removed($1, $3) AS state_leaf_removed
|
||||||
FROM eth.storage_cids
|
FROM eth.storage_cids
|
||||||
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
||||||
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
@ -152,6 +152,8 @@ const (
|
|||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var EmptyNodeValue = make([]byte, common.HashLength)
|
||||||
|
|
||||||
type rctIpldResult struct {
|
type rctIpldResult struct {
|
||||||
LeafCID string `db:"leaf_cid"`
|
LeafCID string `db:"leaf_cid"`
|
||||||
Data []byte `db:"data"`
|
Data []byte `db:"data"`
|
||||||
@ -425,9 +427,10 @@ func (r *IPLDRetriever) RetrieveReceiptByHash(hash common.Hash) (string, []byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
type nodeInfo struct {
|
type nodeInfo struct {
|
||||||
CID string `db:"cid"`
|
CID string `db:"cid"`
|
||||||
Data []byte `db:"data"`
|
Data []byte `db:"data"`
|
||||||
NodeType int `db:"node_type"`
|
NodeType int `db:"node_type"`
|
||||||
|
StateLeafRemoved bool `db:"state_leaf_removed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveAccountByAddressAndBlockHash returns the cid and rlp bytes for the account corresponding to the provided address and block hash
|
// RetrieveAccountByAddressAndBlockHash returns the cid and rlp bytes for the account corresponding to the provided address and block hash
|
||||||
@ -438,9 +441,11 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockHash(address common.Addr
|
|||||||
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockHashPgStr, leafKey.Hex(), hash.Hex()); err != nil {
|
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockHashPgStr, leafKey.Hex(), hash.Hex()); err != nil {
|
||||||
|
|||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if accountResult.NodeType == removedNode {
|
if accountResult.NodeType == removedNode {
|
||||||
return "", []byte{}, nil
|
return "", EmptyNodeValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
||||||
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
||||||
@ -459,9 +464,11 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockNumber(address common.Ad
|
|||||||
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockNumberPgStr, leafKey.Hex(), number); err != nil {
|
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockNumberPgStr, leafKey.Hex(), number); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if accountResult.NodeType == removedNode {
|
if accountResult.NodeType == removedNode {
|
||||||
return "", []byte{}, nil
|
return "", EmptyNodeValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
||||||
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
||||||
@ -480,8 +487,8 @@ func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(add
|
|||||||
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
|
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
|
||||||
return "", nil, nil, err
|
return "", nil, nil, err
|
||||||
}
|
}
|
||||||
if storageResult.NodeType == removedNode {
|
if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode {
|
||||||
return "", []byte{}, []byte{}, nil
|
return "", EmptyNodeValue, EmptyNodeValue, nil
|
||||||
}
|
}
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
|
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
|
||||||
@ -502,8 +509,9 @@ func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockNumber(ad
|
|||||||
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr, stateLeafKey.Hex(), storageLeafKey.Hex(), number); err != nil {
|
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr, stateLeafKey.Hex(), storageLeafKey.Hex(), number); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
if storageResult.NodeType == removedNode {
|
|
||||||
return "", []byte{}, nil
|
if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode {
|
||||||
|
return "", EmptyNodeValue, nil
|
||||||
}
|
}
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
|
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package graphql
|
package graphql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
@ -31,6 +32,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1011,6 +1013,10 @@ func (r *Resolver) GetStorageAt(ctx context.Context, args struct {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bytes.Compare(rlpValue, eth.EmptyNodeValue) == 0 {
|
||||||
|
return &StorageResult{value: eth.EmptyNodeValue, cid: cid, ipldBlock: ipldBlock}, nil
|
||||||
|
}
|
||||||
|
|
||||||
var value interface{}
|
var value interface{}
|
||||||
err = rlp.DecodeBytes(rlpValue, &value)
|
err = rlp.DecodeBytes(rlpValue, &value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -5,8 +5,8 @@ set -o xtrace
|
|||||||
docker-compose down --remove-orphans --volumes
|
docker-compose down --remove-orphans --volumes
|
||||||
|
|
||||||
# Build and start the containers.
|
# Build and start the containers.
|
||||||
# Note: Build only if `ipld-eth-server` code is modified. Otherwise comment this line.
|
# Note: Build only if `ipld-eth-server` or other container code is modified. Otherwise comment this line.
|
||||||
docker build -t ipld-eth-server_eth-server:latest .
|
docker-compose -f docker-compose.test.yml -f docker-compose.yml build eth-server
|
||||||
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d db dapptools contract eth-server
|
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d db dapptools contract eth-server
|
||||||
|
|
||||||
export PGPASSWORD=password
|
export PGPASSWORD=password
|
||||||
|
@ -4,4 +4,7 @@ contract GLDToken is ERC20 {
|
|||||||
constructor() ERC20("Gold", "GLD") {
|
constructor() ERC20("Gold", "GLD") {
|
||||||
_mint(msg.sender, 1000000000000000000000);
|
_mint(msg.sender, 1000000000000000000000);
|
||||||
}
|
}
|
||||||
|
function destroy() public {
|
||||||
|
selfdestruct(payable(msg.sender));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const fastify = require('fastify')({ logger: true });
|
const fastify = require('fastify')({ logger: true });
|
||||||
const hre = require("hardhat");
|
const hre = require("hardhat");
|
||||||
|
|
||||||
|
|
||||||
// readiness check
|
// readiness check
|
||||||
fastify.get('/v1/healthz', async (req, reply) => {
|
fastify.get('/v1/healthz', async (req, reply) => {
|
||||||
reply
|
reply
|
||||||
@ -22,6 +23,20 @@ fastify.get('/v1/deployContract', async (req, reply) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/destroyContract', async (req, reply) => {
|
||||||
|
const addr = req.query.addr;
|
||||||
|
|
||||||
|
const Token = await hre.ethers.getContractFactory("GLDToken");
|
||||||
|
const token = await Token.attach(addr);
|
||||||
|
|
||||||
|
await token.destroy();
|
||||||
|
const blockNum = await hre.ethers.provider.getBlockNumber()
|
||||||
|
|
||||||
|
return {
|
||||||
|
blockNumber: blockNum,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
fastify.get('/v1/sendEth', async (req, reply) => {
|
fastify.get('/v1/sendEth', async (req, reply) => {
|
||||||
const to = req.query.to;
|
const to = req.query.to;
|
||||||
const value = req.query.value;
|
const value = req.query.value;
|
||||||
|
@ -14,6 +14,10 @@ type ContractDeployed struct {
|
|||||||
BlockHash string `json:"blockHash"`
|
BlockHash string `json:"blockHash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ContractDestroyed struct {
|
||||||
|
BlockNumber int64 `json:"blockNumber"`
|
||||||
|
}
|
||||||
|
|
||||||
type Tx struct {
|
type Tx struct {
|
||||||
From string `json:"from"`
|
From string `json:"from"`
|
||||||
To string `json:"to"`
|
To string `json:"to"`
|
||||||
@ -43,6 +47,19 @@ func DeployContract() (*ContractDeployed, error) {
|
|||||||
return &contract, nil
|
return &contract, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DestroyContract(addr string) (*ContractDestroyed, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/destroyContract?addr=%s", srvUrl, addr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var data ContractDestroyed
|
||||||
|
decoder := json.NewDecoder(res.Body)
|
||||||
|
|
||||||
|
return &data, decoder.Decode(&data)
|
||||||
|
}
|
||||||
|
|
||||||
func SendEth(to string, value string) (*Tx, error) {
|
func SendEth(to string, value string) (*Tx, error) {
|
||||||
res, err := http.Get(fmt.Sprintf("%s/v1/sendEth?to=%s&value=%s", srvUrl, to, value))
|
res, err := http.Get(fmt.Sprintf("%s/v1/sendEth?to=%s&value=%s", srvUrl, to, value))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -9,12 +9,13 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
integration "github.com/vulcanize/ipld-eth-server/test"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
|
integration "github.com/vulcanize/ipld-eth-server/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
|
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
|
||||||
@ -391,6 +392,37 @@ var _ = Describe("Integration test", func() {
|
|||||||
Expect(err).To(MatchError("header not found"))
|
Expect(err).To(MatchError("header not found"))
|
||||||
Expect(gethStorage).To(Equal(ipldStorage))
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("get storage after self destruct", func() {
|
||||||
|
totalSupplyIndex := "0x2"
|
||||||
|
|
||||||
|
tx, err := integration.DestroyContract(contract.Address)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
|
||||||
|
gethStorage1, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
gethStorage2, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethStorage1).NotTo(Equal(gethStorage2))
|
||||||
|
Expect(gethStorage2).To(Equal(eth.EmptyNodeValue))
|
||||||
|
|
||||||
|
ipldStorage1, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ipldStorage2, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(ipldStorage1).To(Equal(gethStorage1))
|
||||||
|
Expect(ipldStorage2).To(Equal(gethStorage2))
|
||||||
|
|
||||||
|
// Query the current block
|
||||||
|
ipldStorage3, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(ipldStorage2).To(Equal(ipldStorage3))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("eth call", func() {
|
Describe("eth call", func() {
|
||||||
|
Loading…
Reference in New Issue
Block a user
Just to note, we should only ever see a zero value for a node that is not "Removed" if we are at a block height prior to EIP-158 activation (which is when zeroed value pruning begun). Does this make sense, and align with what we are seeing?
I think we need the analogous check in the account retrieval methods above (
RetrieveAccountByAddressAndBlockNumber
andRetrieveAccountByAddressAndBlockHash
) and the other storage retrieval method below (RetrieveStorageAtByAddressAndStorageKeyAndBlockNumber
).We're running a local/private chain for which the value in genesis is
"eip158Block": 0,
, so this isn't consistent with what we expect?Where is
RetrieveAccountByAddressAndBlockNumber
function called? I couldn't find it. And how to test account deleting?It makes sense but doesn't align with current behavior. Isn't this misalignment was introduced here in this PR https://github.com/vulcanize/go-ethereum/pull/58 ?
Hmm I need to think about this some more, sorry, let me get back.
I think we want to fix the function even if it isn't currently called. We could test account deleting similar to how we do it here: https://github.com/vulcanize/go-ethereum/blob/v1.10.7-statediff/statediff/builder_test.go#L1318
If that is the cause of the misalignment then all we need to do is check that the node isn't a "Removed" type when we query for the latest value at a given path/key, which I think we are already doing?
@arijitAD is taking over here, to echo what I told him in slack:
First thing to do is verify that we are excluding "Removed" type nodes when we perform those queries.
If we arent doing that then we are actually just seeing null values where they are supposed to be, and need to add a check to filter those out
But I think we are already filtering out "Removed" nodes in those queries, and if we are already doing that then there is some deeper reason as to why we are seeing null values for nodes that are not of the "Removed" type
Another possible lead is how we (and geth) are distinguishing (or not) between true nulls and legitimate zero values
On the other side of this coin, if 0 values are not showing up when they are supposed to it is likely because the query being made against the database does not properly consider the "Removed" node type entries as indicating a 0 value and instead the query finds the last entry where the node is not "Removed" and returns that latest non-zero value (which is the behavior we want in some cases, but not here).
Please see https://github.com/vulcanize/ipld-eth-server/issues/95#issuecomment-918202095 there is a much simpler fix now that we have leaf_key for "Removed" nodes