good morning!!!!

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • github/maticnetwork/bor
  • open/bor
2 results
Show changes
Commits on Source (45)
Showing
with 437 additions and 79 deletions
......@@ -13,3 +13,8 @@ jobs:
run: make all
- name: "Run tests"
run: make test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
file: ./cover.out
......@@ -20,7 +20,7 @@ builds:
- netgo
ldflags:
-s -w
- id: darwin-arm64
main: ./cmd/geth
binary: bor
......@@ -35,7 +35,7 @@ builds:
- netgo
ldflags:
-s -w
- id: linux-amd64
main: ./cmd/geth
binary: bor
......@@ -49,7 +49,7 @@ builds:
tags:
- netgo
ldflags:
# We need to build a static binary because we are building in a glibc based system and running in a musl container
# We need to build a static binary because we are building in a glibc based system and running in a musl container
-s -w -extldflags "-static"
- id: linux-arm64
......@@ -65,7 +65,7 @@ builds:
tags:
- netgo
ldflags:
# We need to build a static binary because we are building in a glibc based system and running in a musl container
# We need to build a static binary because we are building in a glibc based system and running in a musl container
-s -w -extldflags "-static"
nfpms:
......@@ -112,7 +112,7 @@ dockers:
extra_files:
- builder/files/genesis-mainnet-v1.json
- builder/files/genesis-testnet-v4.json
- image_templates:
- 0xpolygon/{{ .ProjectName }}:{{ .Version }}-arm64
dockerfile: Dockerfile.release
......
......@@ -48,10 +48,9 @@ ios:
@echo "Done building."
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
test: all
# $(GORUN) build/ci.go test
test:
# Skip mobile and cmd tests since they are being deprecated
go test -v $(go list ./... | grep -v go-ethereum/cmd/ | grep -v go-ethereum/mobile/)
go test -v $$(go list ./... | grep -v go-ethereum/cmd/) -cover -coverprofile=cover.out
lint: ## Run linters.
$(GORUN) build/ci.go lint
......
......@@ -116,6 +116,9 @@ var (
// errOutOfRangeChain is returned if an authorization list is attempted to
// be modified via out-of-range or non-contiguous headers.
errOutOfRangeChain = errors.New("out of range or non-contiguous chain")
// errShutdownDetected is returned if a shutdown was detected
errShutdownDetected = errors.New("shutdown detected")
)
// SignerFn is a signer callback function to request a header to be signed by a
......@@ -916,6 +919,7 @@ func (c *Bor) APIs(chain consensus.ChainHeaderReader) []rpc.API {
// Close implements consensus.Engine. It's a noop for bor as there are no background threads.
func (c *Bor) Close() error {
c.HeimdallClient.Close()
return nil
}
......
......@@ -27,11 +27,13 @@ type IHeimdallClient interface {
Fetch(path string, query string) (*ResponseWithHeight, error)
FetchWithRetry(path string, query string) (*ResponseWithHeight, error)
FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error)
Close()
}
type HeimdallClient struct {
urlString string
client http.Client
closeCh chan struct{}
}
func NewHeimdallClient(urlString string) (*HeimdallClient, error) {
......@@ -40,6 +42,7 @@ func NewHeimdallClient(urlString string) (*HeimdallClient, error) {
client: http.Client{
Timeout: time.Duration(5 * time.Second),
},
closeCh: make(chan struct{}),
}
return h, nil
}
......@@ -96,13 +99,22 @@ func (h *HeimdallClient) FetchWithRetry(rawPath string, rawQuery string) (*Respo
u.Path = rawPath
u.RawQuery = rawQuery
// create a new ticker for retrying the request
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
res, err := h.internalFetch(u)
if err == nil && res != nil {
return res, nil
select {
case <-h.closeCh:
log.Debug("Shutdown detected, terminating request")
return nil, errShutdownDetected
case <-ticker.C:
res, err := h.internalFetch(u)
if err == nil && res != nil {
return res, nil
}
log.Info("Retrying again in 5 seconds for next Heimdall data", "path", u.Path)
}
log.Info("Retrying again in 5 seconds for next Heimdall span", "path", u.Path)
time.Sleep(5 * time.Second)
}
}
......@@ -137,3 +149,9 @@ func (h *HeimdallClient) internalFetch(u *url.URL) (*ResponseWithHeight, error)
return &response, nil
}
// Close sends a signal to stop the running process
func (h *HeimdallClient) Close() {
close(h.closeCh)
h.client.CloseIdleConnections()
}
package core
import (
"math/big"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"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"
)
func TestChain2HeadEvent(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
gspec = &Genesis{
Config: params.TestChainConfig,
Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}},
}
genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config)
)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
chain2HeadCh := make(chan Chain2HeadEvent, 64)
blockchain.SubscribeChain2HeadEvent(chain2HeadCh)
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert chain: %v", err)
}
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) {
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, nil), signer, key1)
if i == 2 {
gen.OffsetTime(-9)
}
if err != nil {
t.Fatalf("failed to create tx: %v", err)
}
gen.AddTx(tx)
})
if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
t.Fatalf("failed to insert chain: %v", err)
}
type eventTest struct {
Type string
Added []common.Hash
Removed []common.Hash
}
readEvent := func(expect *eventTest) {
select {
case ev := <-chain2HeadCh:
if ev.Type != expect.Type {
t.Fatal("Type mismatch")
}
if len(ev.NewChain) != len(expect.Added) {
t.Fatal("Newchain and Added Array Size don't match")
}
if len(ev.OldChain) != len(expect.Removed) {
t.Fatal("Oldchain and Removed Array Size don't match")
}
for j := 0; j < len(ev.OldChain); j++ {
if ev.OldChain[j].Hash() != expect.Removed[j] {
t.Fatal("Oldchain hashes Do Not Match")
}
}
for j := 0; j < len(ev.NewChain); j++ {
if ev.NewChain[j].Hash() != expect.Added[j] {
t.Fatal("Newchain hashes Do Not Match")
}
}
case <-time.After(2 * time.Second):
t.Fatal("timeout")
}
}
// head event
readEvent(&eventTest{
Type: Chain2HeadCanonicalEvent,
Added: []common.Hash{
chain[2].Hash(),
}})
// fork event
readEvent(&eventTest{
Type: Chain2HeadForkEvent,
Added: []common.Hash{
replacementBlocks[0].Hash(),
}})
// fork event
readEvent(&eventTest{
Type: Chain2HeadForkEvent,
Added: []common.Hash{
replacementBlocks[1].Hash(),
}})
// reorg event
//In this event the channel recieves an array of Blocks in NewChain and OldChain
readEvent(&eventTest{
Type: Chain2HeadReorgEvent,
Added: []common.Hash{
replacementBlocks[2].Hash(),
replacementBlocks[1].Hash(),
replacementBlocks[0].Hash(),
},
Removed: []common.Hash{
chain[2].Hash(),
chain[1].Hash(),
chain[0].Hash(),
},
})
// head event
readEvent(&eventTest{
Type: Chain2HeadCanonicalEvent,
Added: []common.Hash{
replacementBlocks[3].Hash(),
}})
}
......@@ -53,6 +53,7 @@ func TestStateProcessorErrors(t *testing.T) {
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Ethash: new(params.EthashConfig),
Bor: &params.BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}},
}
signer = types.LatestSigner(config)
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
......
......@@ -19,18 +19,4 @@ $ bor server
$ bor server --config ./legacy.toml
```
- Modules, vhost and Cors configuration are common for all jsonrpc endpoints.
Before:
```
$ bor --http --http.modules "eth,web" --ws --ws.modules "eth,web"
```
Now:
```
$ bor server --http --ws --jsonrpc.modules "eth,web"
```
- ```Admin```, ```Personal``` and account related endpoints in ```Eth``` are being removed from the JsonRPC interface. Some of this functionality will be moved to the new GRPC server for operational tasks.
......@@ -109,8 +109,6 @@ The ```bor server``` command runs the Bor client.
- ```jsonrpc.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
- ```jsonrpc.modules```: API's offered over the HTTP-RPC interface.
- ```http```: Enable the HTTP-RPC server.
- ```http.addr```: HTTP-RPC server listening interface.
......@@ -119,6 +117,8 @@ The ```bor server``` command runs the Bor client.
- ```http.rpcprefix```: HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
- ```http.modules```: API's offered over the HTTP-RPC interface.
- ```ws```: Enable the WS-RPC server.
- ```ws.addr```: WS-RPC server listening interface.
......@@ -127,6 +127,8 @@ The ```bor server``` command runs the Bor client.
- ```ws.rpcprefix```: HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
- ```ws.modules```: API's offered over the WS-RPC interface.
- ```graphql```: Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.
### P2P Options
......
......@@ -581,10 +581,12 @@ func (s *Ethereum) Stop() error {
// Then stop everything else.
s.bloomIndexer.Close()
close(s.closeBloomHandler)
// closing consensus engine first, as miner has deps on it
s.engine.Close()
s.txPool.Stop()
s.miner.Close()
s.blockchain.Stop()
s.engine.Close()
s.miner.Close()
rawdb.PopUncleanShutdownMarker(s.chainDb)
s.chainDb.Close()
s.eventMux.Stop()
......
......@@ -110,6 +110,8 @@ func generateTestChainWithFork(n int, fork int) (*core.Genesis, []*types.Block,
*/
func TestEth2AssembleBlock(t *testing.T) {
t.Skip("bor due to burn contract")
genesis, blocks := generateTestChain()
n, ethservice := startEthService(t, genesis, blocks[1:9])
defer n.Close()
......@@ -137,6 +139,8 @@ func TestEth2AssembleBlock(t *testing.T) {
}
func TestEth2AssembleBlockWithAnotherBlocksTxs(t *testing.T) {
t.Skip("bor due to burn contract")
genesis, blocks := generateTestChain()
n, ethservice := startEthService(t, genesis, blocks[1:9])
defer n.Close()
......
......@@ -229,7 +229,9 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, et
return clique.New(chainConfig.Clique, db)
}
// If Matic bor consensus is requested, set it up
if chainConfig.Bor != nil {
// In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config
// Then, bor != nil will also be enabled for ethash and clique. Only enable Bor for real if there is a validator contract present.
if chainConfig.Bor != nil && chainConfig.Bor.ValidatorContract != "" {
return bor.New(chainConfig, db, blockchainAPI, ethConfig.HeimdallURL, ethConfig.WithoutHeimdall)
}
// Otherwise assume proof-of-work
......
......@@ -234,6 +234,8 @@ func generateTestChain() (*core.Genesis, []*types.Block) {
}
func TestEthClient(t *testing.T) {
t.Skip("bor due to burn contract")
backend, chain := newTestBackend(t)
client, _ := backend.Attach()
defer backend.Close()
......
......@@ -89,6 +89,8 @@ func generateTestChain() (*core.Genesis, []*types.Block) {
}
func TestGethClient(t *testing.T) {
t.Skip("bor due to burn contract")
backend, _ := newTestBackend(t)
client, err := backend.Attach()
if err != nil {
......
package chains
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
// GetDeveloperChain returns the developer mode configs.
func GetDeveloperChain(period uint64, faucet common.Address) *Chain {
// Override the default period to the user requested one
config := *params.AllCliqueProtocolChanges
config.Clique = &params.CliqueConfig{
Period: period,
Epoch: config.Clique.Epoch,
}
// Assemble and return the chain having genesis with the
// precompiles and faucet pre-funded
return &Chain{
Hash: common.Hash{},
NetworkId: 1337,
Genesis: &core.Genesis{
Config: &config,
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
GasLimit: 11500000,
BaseFee: big.NewInt(params.InitialBaseFee),
Difficulty: big.NewInt(1),
Alloc: map[common.Address]core.GenesisAccount{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
},
},
Bootnodes: []string{},
}
}
......@@ -14,6 +14,8 @@ import (
godebug "runtime/debug"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/eth/downloader"
......@@ -91,6 +93,9 @@ type Config struct {
// GRPC has the grpc server related settings
GRPC *GRPCConfig
// Developer has the developer mode related settings
Developer *DeveloperConfig
}
type P2PConfig struct {
......@@ -209,9 +214,6 @@ type JsonRPCConfig struct {
// IPCPath is the path of the ipc endpoint
IPCPath string `hcl:"ipc-path,optional"`
// Modules is the list of enabled api modules
Modules []string `hcl:"modules,optional"`
// VHost is the list of valid virtual hosts
VHost []string `hcl:"vhost,optional"`
......@@ -251,6 +253,9 @@ type APIConfig struct {
// Host is the address to bind the api
Host string `hcl:"host,optional"`
// Modules is the list of enabled api modules
Modules []string `hcl:"modules,optional"`
}
type GpoConfig struct {
......@@ -365,6 +370,14 @@ type AccountsConfig struct {
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`
}
type DeveloperConfig struct {
// Enabled enables the developer mode
Enabled bool `hcl:"dev,optional"`
// Period is the block period to use in developer mode
Period uint64 `hcl:"period,optional"`
}
func DefaultConfig() *Config {
return &Config{
Chain: "mainnet",
......@@ -425,7 +438,6 @@ func DefaultConfig() *Config {
JsonRPC: &JsonRPCConfig{
IPCDisable: false,
IPCPath: "",
Modules: []string{"web3", "net"},
Cors: []string{"*"},
VHost: []string{"*"},
GasCap: ethconfig.Defaults.RPCGasCap,
......@@ -435,12 +447,14 @@ func DefaultConfig() *Config {
Port: 8545,
Prefix: "",
Host: "localhost",
Modules: []string{"web3", "net"},
},
Ws: &APIConfig{
Enabled: false,
Port: 8546,
Prefix: "",
Host: "localhost",
Modules: []string{"web3", "net"},
},
Graphql: &APIConfig{
Enabled: false,
......@@ -486,6 +500,10 @@ func DefaultConfig() *Config {
GRPC: &GRPCConfig{
Addr: ":3131",
},
Developer: &DeveloperConfig{
Enabled: false,
Period: 0,
},
}
}
......@@ -573,6 +591,9 @@ func readConfigFile(path string) (*Config, error) {
}
func (c *Config) loadChain() error {
if c.Developer.Enabled {
return nil
}
chain, ok := chains.GetChain(c.Chain)
if !ok {
return fmt.Errorf("chain '%s' not found", c.Chain)
......@@ -585,7 +606,7 @@ func (c *Config) loadChain() error {
}
// depending on the chain we have different cache values
if c.Chain != "mainnet" {
if c.Chain == "mainnet" {
c.Cache.Cache = 4096
} else {
c.Cache.Cache = 1024
......@@ -593,14 +614,19 @@ func (c *Config) loadChain() error {
return nil
}
func (c *Config) buildEth() (*ethconfig.Config, error) {
func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
dbHandles, err := makeDatabaseHandles()
if err != nil {
return nil, err
}
n := ethconfig.Defaults
n.NetworkId = c.chain.NetworkId
n.Genesis = c.chain.Genesis
// only update for non-developer mode as we don't yet
// have the chain object for it.
if !c.Developer.Enabled {
n.NetworkId = c.chain.NetworkId
n.Genesis = c.chain.Genesis
}
n.HeimdallURL = c.Heimdall.URL
n.WithoutHeimdall = c.Heimdall.Without
......@@ -640,6 +666,55 @@ func (c *Config) buildEth() (*ethconfig.Config, error) {
}
}
// update for developer mode
if c.Developer.Enabled {
// Get a keystore
var ks *keystore.KeyStore
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore)
}
// Create new developer account or reuse existing one
var (
developer accounts.Account
passphrase string
err error
)
// etherbase has been set above, configuring the miner address from command line flags.
if n.Miner.Etherbase != (common.Address{}) {
developer = accounts.Account{Address: n.Miner.Etherbase}
} else if accs := ks.Accounts(); len(accs) > 0 {
developer = ks.Accounts()[0]
} else {
developer, err = ks.NewAccount(passphrase)
if err != nil {
return nil, fmt.Errorf("failed to create developer account: %v", err)
}
}
if err := ks.Unlock(developer, passphrase); err != nil {
return nil, fmt.Errorf("failed to unlock developer account: %v", err)
}
log.Info("Using developer account", "address", developer.Address)
// get developer mode chain config
c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address)
// update the parameters
n.NetworkId = c.chain.NetworkId
n.Genesis = c.chain.Genesis
// Update cache
c.Cache.Cache = 1024
// Update sync mode
c.SyncMode = "full"
// update miner gas price
if n.Miner.GasPrice == nil {
n.Miner.GasPrice = big.NewInt(1)
}
}
// discovery (this params should be in node.Config)
{
n.EthDiscoveryURLs = c.P2P.Discovery.DNS
......@@ -777,17 +852,28 @@ func (c *Config) buildNode() (*node.Config, error) {
ListenAddr: c.P2P.Bind + ":" + strconv.Itoa(int(c.P2P.Port)),
DiscoveryV5: c.P2P.Discovery.V5Enabled,
},
HTTPModules: c.JsonRPC.Modules,
HTTPModules: c.JsonRPC.Http.Modules,
HTTPCors: c.JsonRPC.Cors,
HTTPVirtualHosts: c.JsonRPC.VHost,
HTTPPathPrefix: c.JsonRPC.Http.Prefix,
WSModules: c.JsonRPC.Modules,
WSModules: c.JsonRPC.Ws.Modules,
WSOrigins: c.JsonRPC.Cors,
WSPathPrefix: c.JsonRPC.Ws.Prefix,
GraphQLCors: c.JsonRPC.Cors,
GraphQLVirtualHosts: c.JsonRPC.VHost,
}
// dev mode
if c.Developer.Enabled {
cfg.UseLightweightKDF = true
// disable p2p networking
c.P2P.NoDiscover = true
cfg.P2P.ListenAddr = ""
cfg.P2P.NoDial = true
cfg.P2P.DiscoveryV5 = false
}
// enable jsonrpc endpoints
{
if c.JsonRPC.Http.Enabled {
......@@ -806,23 +892,26 @@ func (c *Config) buildNode() (*node.Config, error) {
}
cfg.P2P.NAT = natif
// Discovery
// if no bootnodes are defined, use the ones from the chain file.
bootnodes := c.P2P.Discovery.Bootnodes
if len(bootnodes) == 0 {
bootnodes = c.chain.Bootnodes
}
if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil {
return nil, err
}
if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil {
return nil, err
}
if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil {
return nil, err
}
if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil {
return nil, err
// only check for non-developer modes
if !c.Developer.Enabled {
// Discovery
// if no bootnodes are defined, use the ones from the chain file.
bootnodes := c.P2P.Discovery.Bootnodes
if len(bootnodes) == 0 {
bootnodes = c.chain.Bootnodes
}
if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil {
return nil, err
}
if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil {
return nil, err
}
if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil {
return nil, err
}
if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil {
return nil, err
}
}
if c.P2P.NoDiscover {
......
......@@ -16,7 +16,7 @@ func TestConfigDefault(t *testing.T) {
_, err := config.buildNode()
assert.NoError(t, err)
_, err = config.buildEth()
_, err = config.buildEth(nil)
assert.NoError(t, err)
}
......
......@@ -263,11 +263,6 @@ func (c *Command) Flags() *flagset.Flagset {
Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
Value: &c.cliConfig.JsonRPC.VHost,
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "jsonrpc.modules",
Usage: "API's offered over the HTTP-RPC interface",
Value: &c.cliConfig.JsonRPC.Modules,
})
// http options
f.BoolFlag(&flagset.BoolFlag{
......@@ -290,6 +285,12 @@ func (c *Command) Flags() *flagset.Flagset {
Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
Value: &c.cliConfig.JsonRPC.Http.Prefix,
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "http.modules",
Usage: "API's offered over the HTTP-RPC interface",
Value: &c.cliConfig.JsonRPC.Http.Modules,
})
// ws options
f.BoolFlag(&flagset.BoolFlag{
Name: "ws",
......@@ -311,6 +312,12 @@ func (c *Command) Flags() *flagset.Flagset {
Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
Value: &c.cliConfig.JsonRPC.Ws.Prefix,
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "ws.modules",
Usage: "API's offered over the WS-RPC interface",
Value: &c.cliConfig.JsonRPC.Ws.Modules,
})
// graphql options
f.BoolFlag(&flagset.BoolFlag{
Name: "graphql",
......@@ -461,5 +468,17 @@ func (c *Command) Flags() *flagset.Flagset {
Usage: "Address and port to bind the GRPC server",
Value: &c.cliConfig.GRPC.Addr,
})
// developer
f.BoolFlag(&flagset.BoolFlag{
Name: "dev",
Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled",
Value: &c.cliConfig.Developer.Enabled,
})
f.Uint64Flag(&flagset.Uint64Flag{
Name: "dev.period",
Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
Value: &c.cliConfig.Developer.Period,
})
return f
}
......@@ -69,11 +69,22 @@ func NewServer(config *Config) (*Server, error) {
}
srv.node = stack
// setup account manager (only keystore)
{
keydir := stack.KeyStoreDir()
n, p := keystore.StandardScryptN, keystore.StandardScryptP
if config.Accounts.UseLightweightKDF {
n, p = keystore.LightScryptN, keystore.LightScryptP
}
stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))
}
// register the ethereum backend
ethCfg, err := config.buildEth()
ethCfg, err := config.buildEth(stack)
if err != nil {
return nil, err
}
backend, err := eth.New(stack, ethCfg)
if err != nil {
return nil, err
......@@ -85,7 +96,7 @@ func NewServer(config *Config) (*Server, error) {
// graphql is started from another place
if config.JsonRPC.Graphql.Enabled {
if err := graphql.New(stack, backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.Modules); err != nil {
if err := graphql.New(stack, backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.VHost); err != nil {
return nil, fmt.Errorf("failed to register the GraphQL service: %v", err)
}
}
......@@ -97,18 +108,8 @@ func NewServer(config *Config) (*Server, error) {
}
}
// setup account manager (only keystore)
{
keydir := stack.KeyStoreDir()
n, p := keystore.StandardScryptN, keystore.StandardScryptP
if config.Accounts.UseLightweightKDF {
n, p = keystore.LightScryptN, keystore.LightScryptP
}
stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))
}
// sealing (if enabled)
if config.Sealer.Enabled {
// sealing (if enabled) or in dev mode
if config.Sealer.Enabled || config.Developer.Enabled {
if err := backend.StartMining(1); err != nil {
return nil, err
}
......
package server
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestServer_DeveloperMode(t *testing.T) {
// get the default config
config := DefaultConfig()
// enable developer mode
config.Developer.Enabled = true
config.Developer.Period = 2 // block time
// start the server
server, err1 := NewServer(config)
if err1 != nil {
t.Fatalf("failed to start server: %v", err1)
}
// record the initial block number
blockNumber := server.backend.BlockChain().CurrentBlock().Header().Number.Int64()
var i int64 = 0
for i = 0; i < 10; i++ {
// We expect the node to mine blocks every `config.Developer.Period` time period
time.Sleep(time.Duration(config.Developer.Period) * time.Second)
currBlock := server.backend.BlockChain().CurrentBlock().Header().Number.Int64()
expected := blockNumber + i + 1
if res := assert.Equal(t, currBlock, expected); res == false {
break
}
}
// stop the server
server.Stop()
}