Add integration test and dynamic txn unit test.
This commit is contained in:
parent
93e3dba443
commit
80bcb2580f
21
Makefile
Normal file
21
Makefile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
BIN = $(GOPATH)/bin
|
||||||
|
BASE = $(GOPATH)/src/$(PACKAGE)
|
||||||
|
PKGS = go list ./... | grep -v "^vendor/"
|
||||||
|
|
||||||
|
# Tools
|
||||||
|
## Testing library
|
||||||
|
GINKGO = $(BIN)/ginkgo
|
||||||
|
$(BIN)/ginkgo:
|
||||||
|
go get -u github.com/onsi/ginkgo/ginkgo
|
||||||
|
|
||||||
|
.PHONY: integrationtest
|
||||||
|
integrationtest: | $(GINKGO) $(GOOSE)
|
||||||
|
go vet ./...
|
||||||
|
go fmt ./...
|
||||||
|
$(GINKGO) -r test/ -v
|
||||||
|
|
||||||
|
.PHONY: integrationtest_local
|
||||||
|
integrationtest_local: | $(GINKGO) $(GOOSE)
|
||||||
|
go vet ./...
|
||||||
|
go fmt ./...
|
||||||
|
./scripts/run_integration_test.sh
|
@ -36,7 +36,8 @@ func stateValidator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trail := viper.GetUint64("validate.trail")
|
trail := viper.GetUint64("validate.trail")
|
||||||
srvc := validator.NewService(cfg.DB, height, trail)
|
// TODO: add chain config logic here.
|
||||||
|
srvc := validator.NewService(cfg.DB, height, trail, nil)
|
||||||
|
|
||||||
_, err = srvc.Start(context.Background())
|
_, err = srvc.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
46
docker-compose.yml
Normal file
46
docker-compose.yml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
version: '3.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
contract:
|
||||||
|
depends_on:
|
||||||
|
- dapptools
|
||||||
|
build:
|
||||||
|
context: ./test/contract
|
||||||
|
args:
|
||||||
|
ETH_ADDR: "http://dapptools:8545"
|
||||||
|
environment:
|
||||||
|
ETH_ADDR: "http://dapptools:8545"
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:3000:3000"
|
||||||
|
|
||||||
|
dapptools:
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- ipld-eth-db
|
||||||
|
image: vulcanize/dapptools:v0.30.0-v1.10.14-statediff-0.0.29
|
||||||
|
environment:
|
||||||
|
DB_USER: vdbm
|
||||||
|
DB_NAME: vulcanize_testing
|
||||||
|
DB_HOST: ipld-eth-db
|
||||||
|
DB_PORT: 5432
|
||||||
|
DB_PASSWORD: password
|
||||||
|
DB_WRITE: $DB_WRITE
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8545:8545"
|
||||||
|
- "127.0.0.1:8546:8546"
|
||||||
|
|
||||||
|
ipld-eth-db:
|
||||||
|
restart: always
|
||||||
|
image: vulcanize/ipld-eth-db:v0.2.0
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: "vdbm"
|
||||||
|
POSTGRES_DB: "vulcanize_testing"
|
||||||
|
POSTGRES_PASSWORD: "password"
|
||||||
|
volumes:
|
||||||
|
- vdb_db_eth_validator:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8077:5432"
|
||||||
|
command: ["postgres", "-c", "log_statement=all"]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
vdb_db_eth_validator:
|
@ -10,7 +10,23 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testChainConfig = ¶ms.ChainConfig{
|
var IntegrationTestChainConfig = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(4),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
Clique: ¶ms.CliqueConfig{
|
||||||
|
Period: 0,
|
||||||
|
Epoch: 30000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var TestChainConfig = ¶ms.ChainConfig{
|
||||||
ChainID: big.NewInt(1),
|
ChainID: big.NewInt(1),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
EIP150Block: big.NewInt(0),
|
EIP150Block: big.NewInt(0),
|
||||||
@ -22,7 +38,7 @@ var testChainConfig = ¶ms.ChainConfig{
|
|||||||
IstanbulBlock: big.NewInt(0),
|
IstanbulBlock: big.NewInt(0),
|
||||||
MuirGlacierBlock: big.NewInt(0),
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
BerlinBlock: big.NewInt(0),
|
BerlinBlock: big.NewInt(0),
|
||||||
LondonBlock: big.NewInt(100),
|
LondonBlock: big.NewInt(6),
|
||||||
ArrowGlacierBlock: big.NewInt(0),
|
ArrowGlacierBlock: big.NewInt(0),
|
||||||
Ethash: new(params.EthashConfig),
|
Ethash: new(params.EthashConfig),
|
||||||
}
|
}
|
||||||
|
@ -29,21 +29,22 @@ import (
|
|||||||
var (
|
var (
|
||||||
big8 = big.NewInt(8)
|
big8 = big.NewInt(8)
|
||||||
big32 = big.NewInt(32)
|
big32 = big.NewInt(32)
|
||||||
testHash = common.HexToHash("0x1283a0bca5cce009bcf3e5a860eccdc202d1345f464024f2ee8ea1e1254349e7")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
db *postgres.DB
|
db *postgres.DB
|
||||||
blockNum, trail uint64
|
blockNum, trail uint64
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
|
chainCfg *params.ChainConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(db *postgres.DB, blockNum, trailNum uint64) *service {
|
func NewService(db *postgres.DB, blockNum, trailNum uint64, chainCfg *params.ChainConfig) *service {
|
||||||
return &service{
|
return &service{
|
||||||
db: db,
|
db: db,
|
||||||
blockNum: blockNum,
|
blockNum: blockNum,
|
||||||
trail: trailNum,
|
trail: trailNum,
|
||||||
logger: log.New(),
|
logger: log.New(),
|
||||||
|
chainCfg: chainCfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ func NewDB(connectString string, config postgres.ConnectionConfig, node node.Inf
|
|||||||
|
|
||||||
// Start is used to begin the service
|
// Start is used to begin the service
|
||||||
func (s *service) Start(ctx context.Context) (uint64, error) {
|
func (s *service) Start(ctx context.Context) (uint64, error) {
|
||||||
api, err := ethAPI(ctx, s.db)
|
api, err := ethAPI(ctx, s.db, s.chainCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -126,7 +127,6 @@ func (s *service) Start(ctx context.Context) (uint64, error) {
|
|||||||
|
|
||||||
s.logger.Infof("state root verified for block= %d", idxBlockNum)
|
s.logger.Infof("state root verified for block= %d", idxBlockNum)
|
||||||
|
|
||||||
// again fetch head block
|
|
||||||
headBlock, err = api.B.BlockByNumber(ctx, rpc.LatestBlockNumber)
|
headBlock, err = api.B.BlockByNumber(ctx, rpc.LatestBlockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return idxBlockNum, err
|
return idxBlockNum, err
|
||||||
@ -136,14 +136,14 @@ func (s *service) Start(ctx context.Context) (uint64, error) {
|
|||||||
idxBlockNum++
|
idxBlockNum++
|
||||||
}
|
}
|
||||||
|
|
||||||
s.logger.Infof("last validated block %v", idxBlockNum)
|
s.logger.Infof("last validated block %v", idxBlockNum-1)
|
||||||
|
|
||||||
return idxBlockNum, nil
|
return idxBlockNum, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ethAPI(ctx context.Context, db *postgres.DB) (*ipldEth.PublicEthAPI, error) {
|
func ethAPI(ctx context.Context, db *postgres.DB, chainCfg *params.ChainConfig) (*ipldEth.PublicEthAPI, error) {
|
||||||
// TODO: decide network for custom chainConfig.
|
// TODO: decide network for custom chainConfig.
|
||||||
backend, err := NewEthBackend(db, &ipldEth.Config{
|
backend, err := NewEthBackend(db, &ipldEth.Config{
|
||||||
|
ChainConfig: chainCfg,
|
||||||
GroupCacheConfig: ðServerShared.GroupCacheConfig{
|
GroupCacheConfig: ðServerShared.GroupCacheConfig{
|
||||||
StateDB: ethServerShared.GroupConfig{
|
StateDB: ethServerShared.GroupConfig{
|
||||||
Name: "vulcanize_validator",
|
Name: "vulcanize_validator",
|
||||||
@ -161,7 +161,6 @@ func ethAPI(ctx context.Context, db *postgres.DB) (*ipldEth.PublicEthAPI, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
backend.Config.ChainConfig = setChainConfig(genesisBlock.Hash())
|
backend.Config.ChainConfig = setChainConfig(genesisBlock.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,8 +258,6 @@ func setChainConfig(ghash common.Hash) *params.ChainConfig {
|
|||||||
return params.RinkebyChainConfig
|
return params.RinkebyChainConfig
|
||||||
case ghash == params.GoerliGenesisHash:
|
case ghash == params.GoerliGenesisHash:
|
||||||
return params.GoerliChainConfig
|
return params.GoerliChainConfig
|
||||||
case ghash == testHash:
|
|
||||||
return testChainConfig
|
|
||||||
default:
|
default:
|
||||||
return params.AllEthashProtocolChanges
|
return params.AllEthashProtocolChanges
|
||||||
}
|
}
|
||||||
|
23
scripts/run_integration_test.sh
Executable file
23
scripts/run_integration_test.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
set -e
|
||||||
|
set -o xtrace
|
||||||
|
|
||||||
|
export ETH_FORWARD_ETH_CALLS=false
|
||||||
|
export DB_WRITE=true
|
||||||
|
export ETH_HTTP_PATH=""
|
||||||
|
export ETH_PROXY_ON_ERROR=false
|
||||||
|
|
||||||
|
# Clear up existing docker images and volume.
|
||||||
|
docker-compose down --remove-orphans --volumes
|
||||||
|
|
||||||
|
# Build and start the containers.
|
||||||
|
docker-compose -f docker-compose.yml up -d ipld-eth-db dapptools contract
|
||||||
|
|
||||||
|
export PGPASSWORD=password
|
||||||
|
export DATABASE_USER=vdbm
|
||||||
|
export DATABASE_PORT=8077
|
||||||
|
export DATABASE_PASSWORD=password
|
||||||
|
export DATABASE_HOSTNAME=127.0.0.1
|
||||||
|
|
||||||
|
# Wait for containers to be up and execute the integration test.
|
||||||
|
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
|
||||||
|
make integrationtest
|
3
test/contract/.dockerignore
Normal file
3
test/contract/.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
artifacts
|
||||||
|
cache
|
5
test/contract/.gitignore
vendored
Normal file
5
test/contract/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
|
||||||
|
#Hardhat files
|
||||||
|
cache
|
||||||
|
artifacts
|
14
test/contract/Dockerfile
Normal file
14
test/contract/Dockerfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
FROM node:14
|
||||||
|
|
||||||
|
ARG ETH_ADDR
|
||||||
|
ENV ETH_ADDR $ETH_ADDR
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
COPY . .
|
||||||
|
RUN npm run compile && ls -lah
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENTRYPOINT ["npm", "start"]
|
10
test/contract/contracts/GLDToken.sol
Normal file
10
test/contract/contracts/GLDToken.sol
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
pragma solidity ^0.8.0;
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
|
contract GLDToken is ERC20 {
|
||||||
|
constructor() ERC20("Gold", "GLD") {
|
||||||
|
_mint(msg.sender, 1000000000000000000000);
|
||||||
|
}
|
||||||
|
function destroy() public {
|
||||||
|
selfdestruct(payable(msg.sender));
|
||||||
|
}
|
||||||
|
}
|
32
test/contract/hardhat.config.js
Normal file
32
test/contract/hardhat.config.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
require("@nomiclabs/hardhat-waffle");
|
||||||
|
|
||||||
|
// This is a sample Hardhat task. To learn how to create your own go to
|
||||||
|
// https://hardhat.org/guides/create-task.html
|
||||||
|
task("accounts", "Prints the list of accounts", async () => {
|
||||||
|
const accounts = await ethers.getSigners();
|
||||||
|
|
||||||
|
for (const account of accounts) {
|
||||||
|
console.log(account.address);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// You need to export an object to set up your config
|
||||||
|
// Go to https://hardhat.org/config/ to learn more
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type import('hardhat/config').HardhatUserConfig
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
solidity: "0.8.0",
|
||||||
|
networks: {
|
||||||
|
local: {
|
||||||
|
url: 'http://127.0.0.1:8545',
|
||||||
|
chainId: 4
|
||||||
|
},
|
||||||
|
docker: {
|
||||||
|
url: process.env.ETH_ADDR,
|
||||||
|
chainId: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
27700
test/contract/package-lock.json
generated
Normal file
27700
test/contract/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
27
test/contract/package.json
Normal file
27
test/contract/package.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "contract",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"compile": "npx hardhat compile",
|
||||||
|
"start": "HARDHAT_NETWORK=docker node src/index.js",
|
||||||
|
"start:local": "ETH_ADDR=http://127.0.0.1:8545 npm run start",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"@openzeppelin/contracts": "^4.0.0",
|
||||||
|
"fastify": "^3.14.2",
|
||||||
|
"hardhat": "^2.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||||
|
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"ethereum-waffle": "^3.3.0",
|
||||||
|
"ethers": "^5.1.0"
|
||||||
|
}
|
||||||
|
}
|
18
test/contract/scripts/deploy.js
Normal file
18
test/contract/scripts/deploy.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const hre = require("hardhat");
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// await hre.run('compile');
|
||||||
|
// We get the contract to deploy
|
||||||
|
const GLDToken = await hre.ethers.getContractFactory("GLDToken");
|
||||||
|
const token = await GLDToken.deploy();
|
||||||
|
await token.deployed();
|
||||||
|
console.log("GLDToken deployed to:", token.address, token.deployTransaction.hash);
|
||||||
|
}
|
||||||
|
// We recommend this pattern to be able to use async/await everywhere
|
||||||
|
// and properly handle errors.
|
||||||
|
main()
|
||||||
|
.then(() => process.exit(0))
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
36
test/contract/scripts/sample-script.js
Normal file
36
test/contract/scripts/sample-script.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// We require the Hardhat Runtime Environment explicitly here. This is optional
|
||||||
|
// but useful for running the script in a standalone fashion through `node <script>`.
|
||||||
|
//
|
||||||
|
// When running the script with `hardhat run <script>` you'll find the Hardhat
|
||||||
|
// Runtime Environment's members available in the global scope.
|
||||||
|
const hre = require("hardhat");
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// Hardhat always runs the compile task when running scripts with its command
|
||||||
|
// line interface.
|
||||||
|
//
|
||||||
|
// If this script is run directly using `node` you may want to call compile
|
||||||
|
// manually to make sure everything is compiled
|
||||||
|
// await hre.run('compile');
|
||||||
|
|
||||||
|
// We get the contract to deploy
|
||||||
|
const Greeter = await hre.ethers.getContractFactory("Greeter");
|
||||||
|
const greeter = await Greeter.deploy("Hello, Hardhat!");
|
||||||
|
|
||||||
|
await greeter.deployed();
|
||||||
|
|
||||||
|
console.log("Greeter deployed to:", greeter.address, "; tx hash: ", greeter.deployTransaction.hash);
|
||||||
|
|
||||||
|
const result = await greeter.setGreeting("Hello 123!");
|
||||||
|
|
||||||
|
console.log("Greeter updated", "; tx hash: ", result.hash, "; block hash: ", result.blockHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We recommend this pattern to be able to use async/await everywhere
|
||||||
|
// and properly handle errors.
|
||||||
|
main()
|
||||||
|
.then(() => process.exit(0))
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
75
test/contract/src/index.js
Normal file
75
test/contract/src/index.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
const fastify = require('fastify')({ logger: true });
|
||||||
|
const hre = require("hardhat");
|
||||||
|
|
||||||
|
|
||||||
|
// readiness check
|
||||||
|
fastify.get('/v1/healthz', async (req, reply) => {
|
||||||
|
reply
|
||||||
|
.code(200)
|
||||||
|
.header('Content-Type', 'application/json; charset=utf-8')
|
||||||
|
.send({ success: true })
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/deployContract', async (req, reply) => {
|
||||||
|
const GLDToken = await hre.ethers.getContractFactory("GLDToken");
|
||||||
|
const token = await GLDToken.deploy();
|
||||||
|
await token.deployed();
|
||||||
|
|
||||||
|
return {
|
||||||
|
address: token.address,
|
||||||
|
txHash: token.deployTransaction.hash,
|
||||||
|
blockNumber: token.deployTransaction.blockNumber,
|
||||||
|
blockHash: token.deployTransaction.blockHash,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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) => {
|
||||||
|
const to = req.query.to;
|
||||||
|
const value = req.query.value;
|
||||||
|
|
||||||
|
const [owner] = await hre.ethers.getSigners();
|
||||||
|
const tx = await owner.sendTransaction({
|
||||||
|
to,
|
||||||
|
value: hre.ethers.utils.parseEther(value)
|
||||||
|
});
|
||||||
|
await tx.wait(1)
|
||||||
|
|
||||||
|
// console.log(tx);
|
||||||
|
// const coinbaseBalance = await hre.ethers.provider.getBalance(owner.address);
|
||||||
|
// const receiverBalance = await hre.ethers.provider.getBalance(to);
|
||||||
|
// console.log(coinbaseBalance.toString(), receiverBalance.toString());
|
||||||
|
|
||||||
|
return {
|
||||||
|
from: tx.from,
|
||||||
|
to: tx.to,
|
||||||
|
//value: tx.value.toString(),
|
||||||
|
txHash: tx.hash,
|
||||||
|
blockNumber: tx.blockNumber,
|
||||||
|
blockHash: tx.blockHash,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
try {
|
||||||
|
await fastify.listen(3000, '0.0.0.0');
|
||||||
|
} catch (err) {
|
||||||
|
fastify.log.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
14
test/contract/test/sample-test.js
Normal file
14
test/contract/test/sample-test.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const { expect } = require("chai");
|
||||||
|
|
||||||
|
describe("Greeter", function() {
|
||||||
|
it("Should return the new greeting once it's changed", async function() {
|
||||||
|
const Greeter = await ethers.getContractFactory("Greeter");
|
||||||
|
const greeter = await Greeter.deploy("Hello, world!");
|
||||||
|
|
||||||
|
await greeter.deployed();
|
||||||
|
expect(await greeter.greet()).to.equal("Hello, world!");
|
||||||
|
|
||||||
|
await greeter.setGreeting("Hola, mundo!");
|
||||||
|
expect(await greeter.greet()).to.equal("Hola, mundo!");
|
||||||
|
});
|
||||||
|
});
|
19
test/integration_suite_test.go
Normal file
19
test/integration_suite_test.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package integration_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntegration(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "integration test suite")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = BeforeSuite(func() {
|
||||||
|
logrus.SetOutput(ioutil.Discard)
|
||||||
|
})
|
65
test/integration_test.go
Normal file
65
test/integration_test.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package integration_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer/node"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"github.com/Vulcanize/ipld-eth-db-validator/pkg/validator"
|
||||||
|
|
||||||
|
integration "github.com/vulcanize/ipld-eth-server/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
const trail = 0
|
||||||
|
|
||||||
|
var randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
|
||||||
|
|
||||||
|
var _ = Describe("Integration test", func() {
|
||||||
|
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var contract *integration.ContractDeployed
|
||||||
|
var contractErr error
|
||||||
|
sleepInterval := 5 * time.Second
|
||||||
|
|
||||||
|
Describe("Validate state", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
if directProxyEthCalls {
|
||||||
|
Skip("skipping no-direct-proxy-forwarding integration tests")
|
||||||
|
}
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Validate state root", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
db, _ := setupDB()
|
||||||
|
srvc := validator.NewService(db, uint64(contract.BlockNumber), trail, validator.IntegrationTestChainConfig)
|
||||||
|
_, err = srvc.Start(ctx)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
func setupDB() (*postgres.DB, error) {
|
||||||
|
uri := postgres.DbConnectionString(postgres.ConnectionParams{
|
||||||
|
User: "vdbm",
|
||||||
|
Password: "password",
|
||||||
|
Hostname: "localhost",
|
||||||
|
Name: "vulcanize_testing",
|
||||||
|
Port: 8077,
|
||||||
|
})
|
||||||
|
return validator.NewDB(uri, postgres.ConnectionConfig{}, node.Info{})
|
||||||
|
}
|
118
validator_test/chain_maker.go
Normal file
118
validator_test/chain_maker.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package validator_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"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/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/Vulcanize/ipld-eth-db-validator/pkg/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test variables
|
||||||
|
var (
|
||||||
|
Testdb = rawdb.NewMemoryDatabase()
|
||||||
|
TestBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
TestBankAddress = crypto.PubkeyToAddress(TestBankKey.PublicKey) //0x71562b71999873DB5b286dF957af199Ec94617F7
|
||||||
|
TestBankFunds = big.NewInt(100000000)
|
||||||
|
Genesis = core.GenesisBlockForTesting(Testdb, TestBankAddress, TestBankFunds)
|
||||||
|
|
||||||
|
Account1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||||
|
Account2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
||||||
|
Account1Addr = crypto.PubkeyToAddress(Account1Key.PublicKey) //0x703c4b2bD70c169f5717101CaeE543299Fc946C7
|
||||||
|
Account2Addr = crypto.PubkeyToAddress(Account2Key.PublicKey) //0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
|
||||||
|
DeploymentTxData = common.Hex2Bytes("608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600180819055506101e2806100676000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806343d726d61461004657806365f3c31a1461005057806373d4a13a1461007e575b600080fd5b61004e61009c565b005b61007c6004803603602081101561006657600080fd5b810190808035906020019092919050505061017b565b005b610086610185565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610141576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061018c6022913960400191505060405180910390fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b8060018190555050565b6001548156fe4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6e2ea265627a7a723158205ba91466129f45285f53176d805117208c231ec6343d7896790e6fc4165b802b64736f6c63430005110032")
|
||||||
|
ContractCode = common.Hex2Bytes("608060405234801561001057600080fd5b50600436106100415760003560e01c806343d726d61461004657806365f3c31a1461005057806373d4a13a1461007e575b600080fd5b61004e61009c565b005b61007c6004803603602081101561006657600080fd5b810190808035906020019092919050505061017b565b005b610086610185565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610141576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061018c6022913960400191505060405180910390fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b8060018190555050565b6001548156fe4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6e2ea265627a7a723158205ba91466129f45285f53176d805117208c231ec6343d7896790e6fc4165b802b64736f6c63430005110032")
|
||||||
|
CodeHash = crypto.Keccak256Hash(ContractCode)
|
||||||
|
ContractAddr common.Address
|
||||||
|
IndexZero = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
IndexOne = "0000000000000000000000000000000000000000000000000000000000000001"
|
||||||
|
ContractSlotPosition = common.FromHex(IndexOne)
|
||||||
|
ContractSlotKeyHash = crypto.Keccak256Hash(ContractSlotPosition)
|
||||||
|
MiningReward = big.NewInt(2000000000000000000)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* test function signatures
|
||||||
|
put function sig: 65f3c31a
|
||||||
|
close function sig: 43d726d6
|
||||||
|
data function sig: 73d4a13a
|
||||||
|
*/
|
||||||
|
func createLondonTransaction(block *core.BlockGen, addr *common.Address, key *ecdsa.PrivateKey) *types.Transaction {
|
||||||
|
londonTrx := types.NewTx(&types.DynamicFeeTx{
|
||||||
|
ChainID: validator.TestChainConfig.ChainID,
|
||||||
|
Nonce: block.TxNonce(*addr),
|
||||||
|
GasTipCap: big.NewInt(50),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
Gas: 21000,
|
||||||
|
To: addr,
|
||||||
|
Value: big.NewInt(1000),
|
||||||
|
Data: []byte{},
|
||||||
|
})
|
||||||
|
|
||||||
|
transactionSigner := types.MakeSigner(validator.TestChainConfig, block.Number())
|
||||||
|
signedTrx1, err := types.SignTx(londonTrx, transactionSigner, key)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
return signedTrx1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeChain creates a chain of n blocks starting at and including parent.
|
||||||
|
// the returned hash chain is ordered head->parent.
|
||||||
|
func MakeChain(n int, parent *types.Block, chainGen func(int, *core.BlockGen)) ([]*types.Block, []types.Receipts, *core.BlockChain) {
|
||||||
|
config := validator.TestChainConfig
|
||||||
|
blocks, receipts := core.GenerateChain(config, parent, ethash.NewFaker(), Testdb, n, chainGen)
|
||||||
|
chain, _ := core.NewBlockChain(Testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||||
|
return append([]*types.Block{parent}, blocks...), receipts, chain
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainGen(i int, block *core.BlockGen) {
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
// In block 1, the test bank sends account #1 some ether.
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), Account1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, TestBankKey)
|
||||||
|
block.AddTx(tx)
|
||||||
|
case 1:
|
||||||
|
// In block 2, the test bank sends some more ether to account #1.
|
||||||
|
// Account1Addr passes it on to account #2.
|
||||||
|
// Account1Addr creates a test contract.
|
||||||
|
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), Account1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, TestBankKey)
|
||||||
|
nonce := block.TxNonce(Account1Addr)
|
||||||
|
tx2, _ := types.SignTx(types.NewTransaction(nonce, Account2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, Account1Key)
|
||||||
|
nonce++
|
||||||
|
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 1000000, big.NewInt(0), DeploymentTxData), signer, Account1Key)
|
||||||
|
ContractAddr = crypto.CreateAddress(Account1Addr, nonce)
|
||||||
|
block.AddTx(tx1)
|
||||||
|
block.AddTx(tx2)
|
||||||
|
block.AddTx(tx3)
|
||||||
|
case 2:
|
||||||
|
block.SetCoinbase(Account2Addr)
|
||||||
|
data := common.Hex2Bytes("65F3C31A0000000000000000000000000000000000000000000000000000000000000003")
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), ContractAddr, big.NewInt(0), 100000, nil, data), signer, TestBankKey)
|
||||||
|
block.AddTx(tx)
|
||||||
|
case 3:
|
||||||
|
block.SetCoinbase(Account2Addr)
|
||||||
|
data := common.Hex2Bytes("65F3C31A0000000000000000000000000000000000000000000000000000000000000009")
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), ContractAddr, big.NewInt(0), 100000, nil, data), signer, TestBankKey)
|
||||||
|
block.AddTx(tx)
|
||||||
|
case 4:
|
||||||
|
block.SetCoinbase(Account1Addr)
|
||||||
|
data := common.Hex2Bytes("65F3C31A0000000000000000000000000000000000000000000000000000000000000000")
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), ContractAddr, big.NewInt(0), 100000, nil, data), signer, TestBankKey)
|
||||||
|
block.AddTx(tx)
|
||||||
|
case 5:
|
||||||
|
block.AddTx(createLondonTransaction(block, &Account1Addr, Account1Key))
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
block.AddTx(createLondonTransaction(block, &Account2Addr, Account2Key))
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package test
|
package validator_test_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
@ -1,4 +1,4 @@
|
|||||||
package test
|
package validator_test_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -16,16 +16,16 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
||||||
|
|
||||||
"github.com/Vulcanize/ipld-eth-db-validator/pkg/validator"
|
"github.com/Vulcanize/ipld-eth-db-validator/pkg/validator"
|
||||||
|
"github.com/Vulcanize/ipld-eth-db-validator/validator_test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
chainLength = 20
|
chainLength = 20
|
||||||
blockHeight = 1
|
blockHeight = 1
|
||||||
trail = 15
|
trail = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetupDB is use to setup a db for watcher tests
|
// SetupDB is use to setup a db for watcher tests
|
||||||
@ -34,8 +34,8 @@ func setupDB() (*postgres.DB, error) {
|
|||||||
User: "vdbm",
|
User: "vdbm",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
Hostname: "localhost",
|
Hostname: "localhost",
|
||||||
Name: "vulcanize_public",
|
Name: "vulcanize_testing",
|
||||||
Port: 5432,
|
Port: 8077,
|
||||||
})
|
})
|
||||||
return postgres.NewDB(uri, postgres.ConnectionConfig{}, node.Info{})
|
return postgres.NewDB(uri, postgres.ConnectionConfig{}, node.Info{})
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
// make the test blockchain (and state)
|
// make the test blockchain (and state)
|
||||||
blocks, receipts, chain = test_helpers.MakeChain(chainLength, test_helpers.Genesis, test_helpers.TestChainGen)
|
blocks, receipts, chain = validator_test.MakeChain(chainLength, test_helpers.Genesis, validator_test.TestChainGen)
|
||||||
params := statediff.Params{
|
params := statediff.Params{
|
||||||
IntermediateStateNodes: true,
|
IntermediateStateNodes: true,
|
||||||
IntermediateStorageNodes: true,
|
IntermediateStorageNodes: true,
|
||||||
@ -134,7 +134,7 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
|
|
||||||
Describe("state_validation", func() {
|
Describe("state_validation", func() {
|
||||||
It("Validator", func() {
|
It("Validator", func() {
|
||||||
srvc := validator.NewService(db, blockHeight, trail)
|
srvc := validator.NewService(db, blockHeight, trail, validator.TestChainConfig)
|
||||||
|
|
||||||
_, err := srvc.Start(context.Background())
|
_, err := srvc.Start(context.Background())
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
Loading…
Reference in New Issue
Block a user