geth/params: node settings implemented #116
This commit is contained in:
parent
34b19e6af9
commit
031eeb33b8
8
Makefile
8
Makefile
|
@ -49,6 +49,7 @@ statusgo-ios-simulator-mainnet: xgo
|
||||||
|
|
||||||
ci:
|
ci:
|
||||||
build/env.sh go test -v -cover ./geth
|
build/env.sh go test -v -cover ./geth
|
||||||
|
build/env.sh go test -v -cover ./geth/params
|
||||||
build/env.sh go test -v -cover ./geth/jail
|
build/env.sh go test -v -cover ./geth/jail
|
||||||
build/env.sh go test -v -cover ./extkeys
|
build/env.sh go test -v -cover ./extkeys
|
||||||
|
|
||||||
|
@ -56,6 +57,8 @@ test:
|
||||||
@build/env.sh echo "mode: set" > coverage-all.out
|
@build/env.sh echo "mode: set" > coverage-all.out
|
||||||
build/env.sh go test -coverprofile=coverage.out -covermode=set ./geth
|
build/env.sh go test -coverprofile=coverage.out -covermode=set ./geth
|
||||||
@build/env.sh tail -n +2 coverage.out >> coverage-all.out
|
@build/env.sh tail -n +2 coverage.out >> coverage-all.out
|
||||||
|
build/env.sh go test -coverprofile=coverage.out -covermode=set ./geth/params
|
||||||
|
@build/env.sh tail -n +2 coverage.out >> coverage-all.out
|
||||||
build/env.sh go test -coverprofile=coverage.out -covermode=set ./geth/jail
|
build/env.sh go test -coverprofile=coverage.out -covermode=set ./geth/jail
|
||||||
@build/env.sh tail -n +2 coverage.out >> coverage-all.out
|
@build/env.sh tail -n +2 coverage.out >> coverage-all.out
|
||||||
build/env.sh go test -coverprofile=coverage.out -covermode=set ./extkeys
|
build/env.sh go test -coverprofile=coverage.out -covermode=set ./extkeys
|
||||||
|
@ -70,6 +73,11 @@ test-geth:
|
||||||
@build/env.sh go tool cover -html=coverage.out -o coverage.html
|
@build/env.sh go tool cover -html=coverage.out -o coverage.html
|
||||||
@build/env.sh go tool cover -func=coverage.out
|
@build/env.sh go tool cover -func=coverage.out
|
||||||
|
|
||||||
|
test-config:
|
||||||
|
build/env.sh go test -v -coverprofile=coverage.out ./geth/params
|
||||||
|
@build/env.sh go tool cover -html=coverage.out -o coverage.html
|
||||||
|
@build/env.sh go tool cover -func=coverage.out
|
||||||
|
|
||||||
test-jail:
|
test-jail:
|
||||||
build/env.sh go test -v -coverprofile=coverage.out ./geth/jail
|
build/env.sh go test -v -coverprofile=coverage.out ./geth/jail
|
||||||
@build/env.sh go tool cover -html=coverage.out -o coverage.html
|
@build/env.sh go tool cover -html=coverage.out -o coverage.html
|
||||||
|
|
|
@ -9,5 +9,5 @@ fi
|
||||||
|
|
||||||
# set gitCommit when running from a Git checkout.
|
# set gitCommit when running from a Git checkout.
|
||||||
if [ -f ".git/HEAD" ]; then
|
if [ -f ".git/HEAD" ]; then
|
||||||
echo "-ldflags '-X github.com/status-im/status-go/geth.UseTestnetFlag=false -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'";
|
echo "-ldflags '-X github.com/status-im/status-go/geth/params.UseMainnetFlag=true -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'";
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -9,5 +9,5 @@ fi
|
||||||
|
|
||||||
# set gitCommit when running from a Git checkout.
|
# set gitCommit when running from a Git checkout.
|
||||||
if [ -f ".git/HEAD" ]; then
|
if [ -f ".git/HEAD" ]; then
|
||||||
echo "-ldflags '-X github.com/status-im/status-go/geth.UseTestnetFlag=true -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'";
|
echo "-ldflags '-X github.com/status-im/status-go/geth/params.UseMainnetFlag=false -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'";
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
whisper "github.com/ethereum/go-ethereum/whisper/whisperv2"
|
whisper "github.com/ethereum/go-ethereum/whisper/whisperv2"
|
||||||
"github.com/status-im/status-go/geth"
|
"github.com/status-im/status-go/geth"
|
||||||
"github.com/status-im/status-go/geth/jail"
|
"github.com/status-im/status-go/geth/jail"
|
||||||
|
"github.com/status-im/status-go/geth/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
//export CreateAccount
|
//export CreateAccount
|
||||||
|
@ -197,18 +198,29 @@ func DiscardTransactions(ids *C.char) *C.char {
|
||||||
return C.CString(string(outBytes))
|
return C.CString(string(outBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
//export StartNode
|
//export GenerateConfig
|
||||||
func StartNode(datadir *C.char) *C.char {
|
func GenerateConfig(datadir *C.char, networkId C.int) *C.char {
|
||||||
// This starts a geth node with the given datadir
|
config, err := params.NewNodeConfig(C.GoString(datadir), int(networkId))
|
||||||
err := geth.CreateAndRunNode(&geth.NodeConfig{
|
if err != nil {
|
||||||
DataDir: C.GoString(datadir),
|
return makeJSONErrorResponse(err)
|
||||||
IPCEnabled: false,
|
}
|
||||||
HTTPPort: geth.HTTPPort,
|
|
||||||
WSEnabled: false,
|
|
||||||
WSPort: geth.WSPort,
|
|
||||||
TLSEnabled: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
outBytes, err := json.Marshal(&config)
|
||||||
|
if err != nil {
|
||||||
|
return makeJSONErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return C.CString(string(outBytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
//export StartNode
|
||||||
|
func StartNode(configJSON *C.char) *C.char {
|
||||||
|
config, err := params.LoadNodeConfig(C.GoString(configJSON))
|
||||||
|
if err != nil {
|
||||||
|
return makeJSONErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = geth.CreateAndRunNode(config)
|
||||||
return makeJSONErrorResponse(err)
|
return makeJSONErrorResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,19 +242,6 @@ func ResetChainData() *C.char {
|
||||||
return makeJSONErrorResponse(err)
|
return makeJSONErrorResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export StartTLSNode
|
|
||||||
func StartTLSNode(datadir *C.char) *C.char {
|
|
||||||
// This starts a geth node with the given datadir
|
|
||||||
err := geth.CreateAndRunNode(&geth.NodeConfig{
|
|
||||||
DataDir: C.GoString(datadir),
|
|
||||||
HTTPPort: geth.HTTPPort,
|
|
||||||
WSPort: geth.WSPort,
|
|
||||||
TLSEnabled: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return makeJSONErrorResponse(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export StopNodeRPCServer
|
//export StopNodeRPCServer
|
||||||
func StopNodeRPCServer() *C.char {
|
func StopNodeRPCServer() *C.char {
|
||||||
_, err := geth.NodeManagerInstance().StopNodeRPCServer()
|
_, err := geth.NodeManagerInstance().StopNodeRPCServer()
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/status-im/status-go/geth"
|
|
||||||
"github.com/status-im/status-go/geth/params"
|
"github.com/status-im/status-go/geth/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,10 +11,16 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
nodeConfig, err := params.NewNodeConfig(".ethereumcmd", params.TestNetworkId)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
netVersion := "mainnet"
|
netVersion := "mainnet"
|
||||||
if geth.UseTestnet {
|
if nodeConfig.TestNet {
|
||||||
netVersion = "testnet"
|
netVersion = "testnet"
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%s\nVersion: %s\nGit Commit: %s\nBuild Date: %s\nNetwork: %s\n",
|
fmt.Printf("%s\nVersion: %s\nGit Commit: %s\nBuild Date: %s\nNetwork: %s\n",
|
||||||
geth.ClientIdentifier, params.Version, gitCommit, buildStamp, netVersion)
|
nodeConfig.Name, params.Version, gitCommit, buildStamp, netVersion)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -14,18 +15,17 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/les/status"
|
"github.com/ethereum/go-ethereum/les/status"
|
||||||
|
gethparams "github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/status-im/status-go/geth"
|
"github.com/status-im/status-go/geth"
|
||||||
|
"github.com/status-im/status-go/geth/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testConfig *geth.TestConfig
|
var testConfig *geth.TestConfig
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// load shared test configuration
|
// error is ignored, as it will occur on non-test compilation only, and there testConfig is not used at all
|
||||||
var err error
|
// (we have to use "main" package due to restrictions on including C imports into *_test packages)
|
||||||
testConfig, err = geth.LoadTestConfig()
|
testConfig, _ = geth.LoadTestConfig()
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExportedAPI(t *testing.T, done chan struct{}) {
|
func testExportedAPI(t *testing.T, done chan struct{}) {
|
||||||
|
@ -35,6 +35,10 @@ func testExportedAPI(t *testing.T, done chan struct{}) {
|
||||||
name string
|
name string
|
||||||
fn func(t *testing.T) bool
|
fn func(t *testing.T) bool
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
"check default configuration",
|
||||||
|
testGetDefaultConfig,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"reset blockchain data",
|
"reset blockchain data",
|
||||||
testResetChainData,
|
testResetChainData,
|
||||||
|
@ -98,6 +102,97 @@ func testExportedAPI(t *testing.T, done chan struct{}) {
|
||||||
done <- struct{}{}
|
done <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testGetDefaultConfig(t *testing.T) bool {
|
||||||
|
// test Mainnet config
|
||||||
|
nodeConfig := params.NodeConfig{}
|
||||||
|
|
||||||
|
rawResponse := GenerateConfig(C.CString("/tmp/data-folder"), 1)
|
||||||
|
if err := json.Unmarshal([]byte(C.GoString(rawResponse)), &nodeConfig); err != nil {
|
||||||
|
t.Errorf("cannot decode reponse (%s): %v", C.GoString(rawResponse), err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
chainConfig := nodeConfig.ChainConfig
|
||||||
|
if chainConfig.HomesteadBlock.Cmp(gethparams.MainNetHomesteadBlock) != 0 {
|
||||||
|
t.Error("invalid chainConfig.HomesteadBlock")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkBlock.Cmp(gethparams.MainNetDAOForkBlock) != 0 {
|
||||||
|
t.Error("invalid chainConfig.DAOForkBlock")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkSupport != true {
|
||||||
|
t.Error("invalid chainConfig.DAOForkSupport")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Block.Cmp(gethparams.MainNetHomesteadGasRepriceBlock) != 0 {
|
||||||
|
t.Error("invalid chainConfig.EIP150Block")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Hash != gethparams.MainNetHomesteadGasRepriceHash {
|
||||||
|
t.Error("invalid chainConfig.EIP150Hash")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP155Block.Cmp(gethparams.MainNetSpuriousDragon) != 0 {
|
||||||
|
t.Error("invalid chainConfig.EIP155Block")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP158Block.Cmp(gethparams.MainNetSpuriousDragon) != 0 {
|
||||||
|
t.Error("invalid chainConfig.EIP158Block")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.ChainId.Cmp(gethparams.MainNetChainID) != 0 {
|
||||||
|
t.Error("invalid chainConfig.ChainId")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// test Testnet
|
||||||
|
nodeConfig = params.NodeConfig{}
|
||||||
|
rawResponse = GenerateConfig(C.CString("/tmp/data-folder"), 3)
|
||||||
|
if err := json.Unmarshal([]byte(C.GoString(rawResponse)), &nodeConfig); err != nil {
|
||||||
|
t.Errorf("cannot decode reponse (%s): %v", C.GoString(rawResponse), err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
chainConfig = nodeConfig.ChainConfig
|
||||||
|
refChainConfig := gethparams.TestnetChainConfig
|
||||||
|
|
||||||
|
if chainConfig.HomesteadBlock.Cmp(refChainConfig.HomesteadBlock) != 0 {
|
||||||
|
t.Error("invalid chainConfig.HomesteadBlock")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkBlock != nil { // already forked
|
||||||
|
t.Error("invalid chainConfig.DAOForkBlock")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkSupport != refChainConfig.DAOForkSupport {
|
||||||
|
t.Error("invalid chainConfig.DAOForkSupport")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Block.Cmp(refChainConfig.EIP150Block) != 0 {
|
||||||
|
t.Error("invalid chainConfig.EIP150Block")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Hash != refChainConfig.EIP150Hash {
|
||||||
|
t.Error("invalid chainConfig.EIP150Hash")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP155Block.Cmp(refChainConfig.EIP155Block) != 0 {
|
||||||
|
t.Error("invalid chainConfig.EIP155Block")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.EIP158Block.Cmp(refChainConfig.EIP158Block) != 0 {
|
||||||
|
t.Error("invalid chainConfig.EIP158Block")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chainConfig.ChainId.Cmp(refChainConfig.ChainId) != 0 {
|
||||||
|
t.Error("invalid chainConfig.ChainId")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func testResetChainData(t *testing.T) bool {
|
func testResetChainData(t *testing.T) bool {
|
||||||
resetChainDataResponse := geth.JSONError{}
|
resetChainDataResponse := geth.JSONError{}
|
||||||
rawResponse := ResetChainData()
|
rawResponse := ResetChainData()
|
||||||
|
@ -246,7 +341,7 @@ func testRestartNodeRPC(t *testing.T) bool {
|
||||||
t.Errorf("cannot decode StartNodeRPCServer reponse (%s): %v", C.GoString(rawResponse), err)
|
t.Errorf("cannot decode StartNodeRPCServer reponse (%s): %v", C.GoString(rawResponse), err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
expectedError := "HTTP RPC already running on localhost:8545"
|
expectedError := "HTTP RPC already running on localhost:8645"
|
||||||
if startNodeRPCServerResponse.Error != expectedError {
|
if startNodeRPCServerResponse.Error != expectedError {
|
||||||
t.Errorf("expected error not thrown: %s", expectedError)
|
t.Errorf("expected error not thrown: %s", expectedError)
|
||||||
return false
|
return false
|
||||||
|
@ -1213,6 +1308,20 @@ func startTestNode(t *testing.T) <-chan struct{} {
|
||||||
syncRequired = true
|
syncRequired = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepare node directory
|
||||||
|
if err := os.MkdirAll(filepath.Join(geth.TestDataDir, "testnet", "keystore"), os.ModePerm); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// import test account (with test ether on it)
|
||||||
|
dst := filepath.Join(geth.TestDataDir, "testnet", "keystore", "test-account.pk")
|
||||||
|
if _, err := os.Stat(dst); os.IsNotExist(err) {
|
||||||
|
err = geth.CopyFile(dst, filepath.Join(geth.RootDir, "data", "test-account.pk"))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
waitForNodeStart := make(chan struct{}, 1)
|
waitForNodeStart := make(chan struct{}, 1)
|
||||||
geth.SetDefaultNodeNotificationHandler(func(jsonEvent string) {
|
geth.SetDefaultNodeNotificationHandler(func(jsonEvent string) {
|
||||||
t.Log(jsonEvent)
|
t.Log(jsonEvent)
|
||||||
|
@ -1246,12 +1355,18 @@ func startTestNode(t *testing.T) <-chan struct{} {
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
response := StartNode(C.CString(geth.TestDataDir))
|
configJSON := `{
|
||||||
|
"NetworkId": ` + strconv.Itoa(params.TestNetworkId) + `,
|
||||||
|
"DataDir": "` + geth.TestDataDir + `",
|
||||||
|
"HTTPPort": ` + strconv.Itoa(testConfig.Node.HTTPPort) + `,
|
||||||
|
"WSPort": ` + strconv.Itoa(testConfig.Node.WSPort) + `
|
||||||
|
}`
|
||||||
|
response := StartNode(C.CString(configJSON))
|
||||||
err := geth.JSONError{}
|
err := geth.JSONError{}
|
||||||
|
|
||||||
json.Unmarshal([]byte(C.GoString(response)), &err)
|
json.Unmarshal([]byte(C.GoString(response)), &err)
|
||||||
if err.Error != "" {
|
if err.Error != "" {
|
||||||
t.Error("cannot start node")
|
panic("cannot start node: " + err.Error)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"Node": {
|
"Node": {
|
||||||
"SyncSeconds": 45,
|
"SyncSeconds": 90,
|
||||||
"HTTPPort": 8645,
|
"HTTPPort": 8645,
|
||||||
"WSPort": 8646
|
"WSPort": 8646
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/status-im/status-go/geth"
|
"github.com/status-im/status-go/geth"
|
||||||
|
"github.com/status-im/status-go/geth/params"
|
||||||
"github.com/status-im/status-go/geth/jail"
|
"github.com/status-im/status-go/geth/jail"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -636,7 +637,7 @@ func TestContractDeployment(t *testing.T) {
|
||||||
{
|
{
|
||||||
from: '` + testConfig.Account1.Address + `',
|
from: '` + testConfig.Account1.Address + `',
|
||||||
data: '0x6060604052341561000c57fe5b5b60a58061001b6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636ffa1caa14603a575bfe5b3415604157fe5b60556004808035906020019091905050606b565b6040518082815260200191505060405180910390f35b60008160020290505b9190505600a165627a7a72305820ccdadd737e4ac7039963b54cee5e5afb25fa859a275252bdcf06f653155228210029',
|
data: '0x6060604052341561000c57fe5b5b60a58061001b6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636ffa1caa14603a575bfe5b3415604157fe5b60556004808035906020019091905050606b565b6040518082815260200191505060405180910390f35b60008160020290505b9190505600a165627a7a72305820ccdadd737e4ac7039963b54cee5e5afb25fa859a275252bdcf06f653155228210029',
|
||||||
gas: '` + strconv.Itoa(geth.DefaultGas) + `'
|
gas: '` + strconv.Itoa(params.DefaultGas) + `'
|
||||||
}, function (e, contract){
|
}, function (e, contract){
|
||||||
if (!e) {
|
if (!e) {
|
||||||
responseValue = contract.transactionHash
|
responseValue = contract.transactionHash
|
||||||
|
|
205
geth/node.go
205
geth/node.go
|
@ -4,10 +4,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
@ -15,60 +13,23 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/les"
|
"github.com/ethereum/go-ethereum/les"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discv5"
|
"github.com/ethereum/go-ethereum/p2p/discv5"
|
||||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
gethparams "github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
|
||||||
whisper "github.com/ethereum/go-ethereum/whisper/whisperv2"
|
whisper "github.com/ethereum/go-ethereum/whisper/whisperv2"
|
||||||
|
"github.com/status-im/status-go/geth/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClientIdentifier = "StatusIM" // Client identifier to advertise over the network
|
|
||||||
IPCFile = "geth.ipc" // Filename of exposed IPC-RPC Server
|
|
||||||
HTTPPort = 8545 // HTTP-RPC port (replaced in unit tests)
|
|
||||||
WSPort = 8546 // WS-RPC port (replaced in unit tests)
|
|
||||||
MaxPeers = 25
|
|
||||||
MaxLightPeers = 20
|
|
||||||
MaxPendingPeers = 0
|
|
||||||
DefaultGas = 180000
|
|
||||||
|
|
||||||
ProcessFileDescriptorLimit = uint64(2048)
|
|
||||||
DatabaseCacheSize = 128 // Megabytes of memory allocated to internal caching (min 16MB / database forced)
|
|
||||||
|
|
||||||
EventNodeStarted = "node.started"
|
EventNodeStarted = "node.started"
|
||||||
EventNodeCrashed = "node.crashed"
|
EventNodeCrashed = "node.crashed"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Gas price settings
|
|
||||||
var (
|
|
||||||
GasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon) // Minimal gas price to accept for mining a transactions
|
|
||||||
GpoMinGasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon) // Minimum suggested gas price
|
|
||||||
GpoMaxGasPrice = new(big.Int).Mul(big.NewInt(500), common.Shannon) // Maximum suggested gas price
|
|
||||||
GpoFullBlockRatio = 80 // Full block threshold for gas price calculation (%)
|
|
||||||
GpobaseStepDown = 10 // Suggested gas price base step down ratio (1/1000)
|
|
||||||
GpobaseStepUp = 100 // Suggested gas price base step up ratio (1/1000)
|
|
||||||
GpobaseCorrectionFactor = 110 // Suggested gas price base correction factor (%)
|
|
||||||
)
|
|
||||||
|
|
||||||
// default node configuration options
|
|
||||||
var (
|
|
||||||
UseTestnetFlag = "true" // to be overridden via -ldflags '-X geth.UseTestnetFlag'
|
|
||||||
UseTestnet = false
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if UseTestnetFlag == "true" { // set at compile time, here we make sure to set corresponding boolean flag
|
|
||||||
UseTestnet = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// node-related errors
|
// node-related errors
|
||||||
var (
|
var (
|
||||||
ErrEthServiceRegistrationFailure = errors.New("failed to register the Ethereum service")
|
ErrEthServiceRegistrationFailure = errors.New("failed to register the Ethereum service")
|
||||||
|
@ -76,22 +37,12 @@ var (
|
||||||
ErrLightEthRegistrationFailure = errors.New("failed to register the LES service")
|
ErrLightEthRegistrationFailure = errors.New("failed to register the LES service")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeConfig stores configuration options for a node
|
|
||||||
type NodeConfig struct {
|
|
||||||
DataDir string // base data directory
|
|
||||||
IPCEnabled bool // whether IPC-RPC Server is enabled or not
|
|
||||||
HTTPPort int // HTTP-RPC Server port
|
|
||||||
WSPort int // WS-RPC Server port
|
|
||||||
WSEnabled bool // whether WS-RPC Server is enabled or not
|
|
||||||
TLSEnabled bool // whether TLS support should be enabled on node or not
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node represents running node (serves as a wrapper around P2P node)
|
// Node represents running node (serves as a wrapper around P2P node)
|
||||||
type Node struct {
|
type Node struct {
|
||||||
config *NodeConfig // configuration used to create Status node
|
config *params.NodeConfig // configuration used to create Status node
|
||||||
geth *node.Node // reference to the running Geth node
|
geth *node.Node // reference to the running Geth node
|
||||||
gethConfig *node.Config // configuration used to create P2P node
|
gethConfig *node.Config // configuration used to create P2P node
|
||||||
started chan struct{} // channel to wait for node to start
|
started chan struct{} // channel to wait for node to start
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inited checks whether status node has been properly initialized
|
// Inited checks whether status node has been properly initialized
|
||||||
|
@ -105,24 +56,16 @@ func (n *Node) GethStack() *node.Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeNode create a geth node entity
|
// MakeNode create a geth node entity
|
||||||
func MakeNode(config *NodeConfig) *Node {
|
func MakeNode(config *params.NodeConfig) *Node {
|
||||||
glog.CopyStandardLogTo("INFO")
|
glog.CopyStandardLogTo("INFO")
|
||||||
glog.SetToStderr(true)
|
glog.SetToStderr(true)
|
||||||
|
|
||||||
dataDir := config.DataDir
|
|
||||||
if UseTestnet {
|
|
||||||
dataDir = filepath.Join(config.DataDir, "testnet")
|
|
||||||
}
|
|
||||||
|
|
||||||
// exposed RPC APIs
|
|
||||||
exposedAPIs := "db,eth,net,web3,shh,personal,admin" // TODO remove "admin" on main net
|
|
||||||
|
|
||||||
// configure required node (should you need to update node's config, e.g. add bootstrap nodes, see node.Config)
|
// configure required node (should you need to update node's config, e.g. add bootstrap nodes, see node.Config)
|
||||||
stackConfig := &node.Config{
|
stackConfig := &node.Config{
|
||||||
DataDir: dataDir,
|
DataDir: config.DataDir,
|
||||||
UseLightweightKDF: true,
|
UseLightweightKDF: true,
|
||||||
Name: ClientIdentifier,
|
Name: config.Name,
|
||||||
Version: params.Version,
|
Version: config.Version,
|
||||||
NoDiscovery: true,
|
NoDiscovery: true,
|
||||||
DiscoveryV5: false,
|
DiscoveryV5: false,
|
||||||
DiscoveryV5Addr: ":0",
|
DiscoveryV5Addr: ":0",
|
||||||
|
@ -130,17 +73,17 @@ func MakeNode(config *NodeConfig) *Node {
|
||||||
BootstrapNodesV5: makeBootstrapNodesV5(),
|
BootstrapNodesV5: makeBootstrapNodesV5(),
|
||||||
ListenAddr: ":0",
|
ListenAddr: ":0",
|
||||||
NAT: nat.Any(),
|
NAT: nat.Any(),
|
||||||
MaxPeers: MaxPeers,
|
MaxPeers: config.MaxPeers,
|
||||||
MaxPendingPeers: MaxPendingPeers,
|
MaxPendingPeers: config.MaxPendingPeers,
|
||||||
IPCPath: makeIPCPath(dataDir, config.IPCEnabled),
|
IPCPath: makeIPCPath(config),
|
||||||
HTTPHost: node.DefaultHTTPHost,
|
HTTPHost: config.HTTPHost,
|
||||||
HTTPPort: config.HTTPPort,
|
HTTPPort: config.HTTPPort,
|
||||||
HTTPCors: "*",
|
HTTPCors: "*",
|
||||||
HTTPModules: strings.Split(exposedAPIs, ","),
|
HTTPModules: strings.Split(config.APIModules, ","),
|
||||||
WSHost: makeWSHost(config.WSEnabled),
|
WSHost: makeWSHost(config),
|
||||||
WSPort: config.WSPort,
|
WSPort: config.WSPort,
|
||||||
WSOrigins: "*",
|
WSOrigins: "*",
|
||||||
WSModules: strings.Split(exposedAPIs, ","),
|
WSModules: strings.Split(config.APIModules, ","),
|
||||||
}
|
}
|
||||||
|
|
||||||
stack, err := node.New(stackConfig)
|
stack, err := node.New(stackConfig)
|
||||||
|
@ -149,12 +92,12 @@ func MakeNode(config *NodeConfig) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// start Ethereum service
|
// start Ethereum service
|
||||||
if err := activateEthService(stack, makeDefaultExtra()); err != nil {
|
if err := activateEthService(stack, config); err != nil {
|
||||||
Fatalf(fmt.Errorf("%v: %v", ErrEthServiceRegistrationFailure, err))
|
Fatalf(fmt.Errorf("%v: %v", ErrEthServiceRegistrationFailure, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// start Whisper service
|
// start Whisper service
|
||||||
if err := activateShhService(stack); err != nil {
|
if err := activateShhService(stack, config); err != nil {
|
||||||
Fatalf(fmt.Errorf("%v: %v", ErrSshServiceRegistrationFailure, err))
|
Fatalf(fmt.Errorf("%v: %v", ErrSshServiceRegistrationFailure, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,35 +110,29 @@ func MakeNode(config *NodeConfig) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// activateEthService configures and registers the eth.Ethereum service with a given node.
|
// activateEthService configures and registers the eth.Ethereum service with a given node.
|
||||||
func activateEthService(stack *node.Node, extra []byte) error {
|
func activateEthService(stack *node.Node, config *params.NodeConfig) error {
|
||||||
ethConf := ð.Config{
|
ethConf := ð.Config{
|
||||||
Etherbase: common.Address{},
|
Etherbase: common.Address{},
|
||||||
ChainConfig: makeChainConfig(stack),
|
ChainConfig: makeChainConfig(config),
|
||||||
FastSync: false,
|
FastSync: false,
|
||||||
LightMode: true,
|
LightMode: true,
|
||||||
LightServ: 60,
|
MaxPeers: config.MaxPeers,
|
||||||
LightPeers: MaxLightPeers,
|
DatabaseCache: config.LightEthConfig.DatabaseCache,
|
||||||
MaxPeers: MaxPeers,
|
|
||||||
DatabaseCache: DatabaseCacheSize,
|
|
||||||
DatabaseHandles: makeDatabaseHandles(),
|
DatabaseHandles: makeDatabaseHandles(),
|
||||||
NetworkId: 1, // Olympic
|
NetworkId: config.NetworkId,
|
||||||
|
Genesis: config.LightEthConfig.Genesis,
|
||||||
MinerThreads: runtime.NumCPU(),
|
MinerThreads: runtime.NumCPU(),
|
||||||
GasPrice: GasPrice,
|
GasPrice: params.GasPrice,
|
||||||
GpoMinGasPrice: GpoMinGasPrice,
|
GpoMinGasPrice: params.GpoMinGasPrice,
|
||||||
GpoMaxGasPrice: GpoMaxGasPrice,
|
GpoMaxGasPrice: params.GpoMaxGasPrice,
|
||||||
GpoFullBlockRatio: GpoFullBlockRatio,
|
GpoFullBlockRatio: params.GpoFullBlockRatio,
|
||||||
GpobaseStepDown: GpobaseStepDown,
|
GpobaseStepDown: params.GpobaseStepDown,
|
||||||
GpobaseStepUp: GpobaseStepUp,
|
GpobaseStepUp: params.GpobaseStepUp,
|
||||||
GpobaseCorrectionFactor: GpobaseCorrectionFactor,
|
GpobaseCorrectionFactor: params.GpobaseCorrectionFactor,
|
||||||
SolcPath: "solc",
|
SolcPath: "solc",
|
||||||
AutoDAG: false,
|
AutoDAG: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
if UseTestnet {
|
|
||||||
ethConf.NetworkId = 3
|
|
||||||
ethConf.Genesis = core.DefaultTestnetGenesisBlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
return les.New(ctx, ethConf)
|
return les.New(ctx, ethConf)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
@ -206,7 +143,7 @@ func activateEthService(stack *node.Node, extra []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// activateShhService configures Whisper and adds it to the given node.
|
// activateShhService configures Whisper and adds it to the given node.
|
||||||
func activateShhService(stack *node.Node) error {
|
func activateShhService(stack *node.Node, config *params.NodeConfig) error {
|
||||||
serviceConstructor := func(*node.ServiceContext) (node.Service, error) {
|
serviceConstructor := func(*node.ServiceContext) (node.Service, error) {
|
||||||
return whisper.New(), nil
|
return whisper.New(), nil
|
||||||
}
|
}
|
||||||
|
@ -218,47 +155,44 @@ func activateShhService(stack *node.Node) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeIPCPath returns IPC-RPC filename
|
// makeIPCPath returns IPC-RPC filename
|
||||||
func makeIPCPath(dataDir string, ipcEnabled bool) string {
|
func makeIPCPath(config *params.NodeConfig) string {
|
||||||
if !ipcEnabled {
|
if !config.IPCEnabled {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.Join(dataDir, IPCFile)
|
return path.Join(config.DataDir, config.IPCFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeWSHost returns WS-RPC Server host, given enabled/disabled flag
|
// makeWSHost returns WS-RPC Server host, given enabled/disabled flag
|
||||||
func makeWSHost(wsEnabled bool) string {
|
func makeWSHost(config *params.NodeConfig) string {
|
||||||
if !wsEnabled {
|
if !config.WSEnabled {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.DefaultWSHost
|
return config.WSHost
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeChainConfig reads the chain configuration from the database in the datadir.
|
// makeChainConfig reads the chain configuration from the database in the datadir.
|
||||||
func makeChainConfig(stack *node.Node) *params.ChainConfig {
|
func makeChainConfig(config *params.NodeConfig) *gethparams.ChainConfig {
|
||||||
config := new(params.ChainConfig)
|
chainConfig := new(gethparams.ChainConfig)
|
||||||
|
|
||||||
if UseTestnet {
|
// Homestead fork
|
||||||
config = params.TestnetChainConfig
|
chainConfig.HomesteadBlock = config.HomesteadBlock
|
||||||
} else {
|
|
||||||
// Homestead fork
|
|
||||||
config.HomesteadBlock = params.MainNetHomesteadBlock
|
|
||||||
// DAO fork
|
|
||||||
config.DAOForkBlock = params.MainNetDAOForkBlock
|
|
||||||
config.DAOForkSupport = true
|
|
||||||
|
|
||||||
// DoS reprice fork
|
// DAO fork
|
||||||
config.EIP150Block = params.MainNetHomesteadGasRepriceBlock
|
chainConfig.DAOForkBlock = config.DAOForkBlock
|
||||||
config.EIP150Hash = params.MainNetHomesteadGasRepriceHash
|
chainConfig.DAOForkSupport = config.DAOForkSupport
|
||||||
|
|
||||||
// DoS state cleanup fork
|
// DoS reprice fork
|
||||||
config.EIP155Block = params.MainNetSpuriousDragon
|
chainConfig.EIP150Block = config.EIP150Block
|
||||||
config.EIP158Block = params.MainNetSpuriousDragon
|
chainConfig.EIP150Hash = config.EIP150Hash
|
||||||
config.ChainId = params.MainNetChainID
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
// DoS state cleanup fork
|
||||||
|
chainConfig.EIP155Block = config.EIP155Block
|
||||||
|
chainConfig.EIP158Block = config.EIP158Block
|
||||||
|
chainConfig.ChainId = config.ChainId
|
||||||
|
|
||||||
|
return chainConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeDatabaseHandles makes sure that enough file descriptors are available to the process
|
// makeDatabaseHandles makes sure that enough file descriptors are available to the process
|
||||||
|
@ -272,8 +206,8 @@ func makeDatabaseHandles() int {
|
||||||
|
|
||||||
// increase limit
|
// increase limit
|
||||||
limit.Cur = limit.Max
|
limit.Cur = limit.Max
|
||||||
if limit.Cur > ProcessFileDescriptorLimit {
|
if limit.Cur > params.DefaultFileDescriptorLimit {
|
||||||
limit.Cur = ProcessFileDescriptorLimit
|
limit.Cur = params.DefaultFileDescriptorLimit
|
||||||
}
|
}
|
||||||
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
|
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
|
||||||
Fatalf(err)
|
Fatalf(err)
|
||||||
|
@ -285,34 +219,13 @@ func makeDatabaseHandles() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// cap limit
|
// cap limit
|
||||||
if limit.Cur > ProcessFileDescriptorLimit {
|
if limit.Cur > params.DefaultFileDescriptorLimit {
|
||||||
limit.Cur = ProcessFileDescriptorLimit
|
limit.Cur = params.DefaultFileDescriptorLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
return int(limit.Cur) / 2
|
return int(limit.Cur) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeDefaultExtra() []byte {
|
|
||||||
var clientInfo = struct {
|
|
||||||
Version uint
|
|
||||||
Name string
|
|
||||||
GoVersion string
|
|
||||||
Os string
|
|
||||||
}{uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), ClientIdentifier, runtime.Version(), runtime.GOOS}
|
|
||||||
extra, err := rlp.EncodeToBytes(clientInfo)
|
|
||||||
if err != nil {
|
|
||||||
glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
|
|
||||||
glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
|
|
||||||
glog.V(logger.Debug).Infof("extra: %x\n", extra)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return extra
|
|
||||||
}
|
|
||||||
|
|
||||||
// makeBootstrapNodes returns default (hence bootstrap) list of peers
|
// makeBootstrapNodes returns default (hence bootstrap) list of peers
|
||||||
func makeBootstrapNodes() []*discover.Node {
|
func makeBootstrapNodes() []*discover.Node {
|
||||||
// on desktops params.TestnetBootnodes and params.MainBootnodes,
|
// on desktops params.TestnetBootnodes and params.MainBootnodes,
|
||||||
|
|
|
@ -64,7 +64,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateAndRunNode creates and starts running Geth node locally (exposing given RPC port along the way)
|
// CreateAndRunNode creates and starts running Geth node locally (exposing given RPC port along the way)
|
||||||
func CreateAndRunNode(config *NodeConfig) error {
|
func CreateAndRunNode(config *params.NodeConfig) error {
|
||||||
defer HaltOnPanic()
|
defer HaltOnPanic()
|
||||||
|
|
||||||
nodeManager := NewNodeManager(config)
|
nodeManager := NewNodeManager(config)
|
||||||
|
@ -79,7 +79,7 @@ func CreateAndRunNode(config *NodeConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeManager makes new instance of node manager
|
// NewNodeManager makes new instance of node manager
|
||||||
func NewNodeManager(config *NodeConfig) *NodeManager {
|
func NewNodeManager(config *params.NodeConfig) *NodeManager {
|
||||||
createOnce.Do(func() {
|
createOnce.Do(func() {
|
||||||
nodeManagerInstance = &NodeManager{
|
nodeManagerInstance = &NodeManager{
|
||||||
services: &NodeServiceStack{
|
services: &NodeServiceStack{
|
||||||
|
|
|
@ -0,0 +1,275 @@
|
||||||
|
package params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"math/big"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// default node configuration options
|
||||||
|
var (
|
||||||
|
UseMainnetFlag = "false" // to be overridden via -ldflags '-X geth/params.UseMainnetFlag'
|
||||||
|
UseMainnet = false
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if UseMainnetFlag == "true" { // set at compile time, here we make sure to set corresponding boolean flag
|
||||||
|
UseMainnet = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrMissingDataDir = errors.New("missing required 'DataDir' parameter")
|
||||||
|
ErrMissingNetworkId = errors.New("missing required 'NetworkId' parameter")
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChainConfig holds core blockchain settings. It is stored in the database on a per block basis.
|
||||||
|
type ChainConfig struct {
|
||||||
|
// ChainId identifies the current chain and is used for replay protection
|
||||||
|
ChainId *big.Int
|
||||||
|
|
||||||
|
// HomesteadBlock is Homestead switch block (nil = no fork, 0 = already homestead)
|
||||||
|
HomesteadBlock *big.Int
|
||||||
|
|
||||||
|
// DAOForkBlock TheDAO hard-fork switch block (nil = no fork)
|
||||||
|
DAOForkBlock *big.Int
|
||||||
|
|
||||||
|
// DAOForkSupport Whether the nodes supports or opposes the DAO hard-fork
|
||||||
|
DAOForkSupport bool
|
||||||
|
|
||||||
|
// EIP150Block is EIP150 HF block (nil = no fork)
|
||||||
|
EIP150Block *big.Int
|
||||||
|
|
||||||
|
// EIP150Hash is EIP150 HF hash (fast sync aid)
|
||||||
|
EIP150Hash common.Hash
|
||||||
|
|
||||||
|
// EIP155Block is EIP155 HF block
|
||||||
|
EIP155Block *big.Int
|
||||||
|
|
||||||
|
// EIP158Block is EIP158 HF block
|
||||||
|
EIP158Block *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// LightEthConfig holds LES-related configuration
|
||||||
|
// Status nodes are always lightweight clients (due to mobile platform constraints)
|
||||||
|
type LightEthConfig struct {
|
||||||
|
// Genesis is JSON to seed the chain database with
|
||||||
|
Genesis string
|
||||||
|
|
||||||
|
// DatabaseCache is memory (in MBs) allocated to internal caching (min 16MB / database forced)
|
||||||
|
DatabaseCache int
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhisperConfig holds SHH-related configuration
|
||||||
|
type WhisperConfig struct{}
|
||||||
|
|
||||||
|
// SwarmConfig holds Swarm-related configuration
|
||||||
|
type SwarmConfig struct{}
|
||||||
|
|
||||||
|
// NodeConfig stores configuration options for a node
|
||||||
|
type NodeConfig struct {
|
||||||
|
// TestNet flag whether given configuration describes a test or mainnet
|
||||||
|
TestNet bool
|
||||||
|
|
||||||
|
// NetworkId sets network to use for selecting peers to connect to
|
||||||
|
NetworkId int
|
||||||
|
|
||||||
|
// DataDir is the file system folder the node should use for any data storage needs.
|
||||||
|
DataDir string
|
||||||
|
|
||||||
|
// Name sets the instance name of the node. It must not contain the / character.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Version exposes program's version. It is used in the devp2p node identifier.
|
||||||
|
Version string
|
||||||
|
|
||||||
|
// APIModules is a comma-separated list of API modules exposed via *any* (HTTP/WS/IPC) RPC interface.
|
||||||
|
APIModules string
|
||||||
|
|
||||||
|
// HTTPHost is the host interface on which to start the HTTP RPC server.
|
||||||
|
// Pass empty string if no HTTP RPC interface needs to be started.
|
||||||
|
HTTPHost string
|
||||||
|
|
||||||
|
// HTTPPort is the TCP port number on which to start the Geth's HTTP RPC server.
|
||||||
|
HTTPPort int
|
||||||
|
|
||||||
|
// WSHost is a host interface for the WebSocket RPC server
|
||||||
|
WSHost string
|
||||||
|
|
||||||
|
// WSPort is the TCP port number on which to start the Geth's WebSocket RPC server.
|
||||||
|
WSPort int
|
||||||
|
|
||||||
|
// WSEnabled specifies whether WS-RPC Server is enabled or not
|
||||||
|
WSEnabled bool
|
||||||
|
|
||||||
|
// IPCFile is filename of exposed IPC RPC Server
|
||||||
|
IPCFile string
|
||||||
|
|
||||||
|
// IPCEnabled specifies whether IPC-RPC Server is enabled or not
|
||||||
|
IPCEnabled bool
|
||||||
|
|
||||||
|
// TLSEnabled specifies whether TLS support should be enabled on node or not
|
||||||
|
// TLS support is only planned in go-ethereum, so we are using our own patch.
|
||||||
|
TLSEnabled bool
|
||||||
|
|
||||||
|
// MaxPeers is the maximum number of (global) peers that can be connected.
|
||||||
|
// Set to zero, if only static or trusted peers are allowed to connect.
|
||||||
|
MaxPeers int
|
||||||
|
|
||||||
|
// MaxPendingPeers is the maximum number of peers that can be pending in the
|
||||||
|
// handshake phase, counted separately for inbound and outbound connections.
|
||||||
|
MaxPendingPeers int
|
||||||
|
|
||||||
|
// ChainConfig extra configuration for blockchain
|
||||||
|
*ChainConfig `json:"ChainConfig,"`
|
||||||
|
|
||||||
|
// LightEthConfig extra configuration for LES
|
||||||
|
*LightEthConfig `json:"LightEthConfig,"`
|
||||||
|
|
||||||
|
// WhisperConfig extra configuration for SHH
|
||||||
|
*WhisperConfig `json:"WhisperConfig,"`
|
||||||
|
|
||||||
|
// SwarmConfig extra configuration for Swarm and ENS
|
||||||
|
*SwarmConfig `json:"SwarmConfig,"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNodeConfig creates new node configuration object
|
||||||
|
func NewNodeConfig(dataDir string, networkId int) (*NodeConfig, error) {
|
||||||
|
nodeConfig := &NodeConfig{
|
||||||
|
NetworkId: networkId,
|
||||||
|
DataDir: dataDir,
|
||||||
|
Name: DefaultClientIdentifier,
|
||||||
|
Version: Version,
|
||||||
|
HTTPHost: DefaultHTTPHost,
|
||||||
|
HTTPPort: DefaultHTTPPort,
|
||||||
|
APIModules: DefaultAPIModules,
|
||||||
|
WSHost: DefaultWSHost,
|
||||||
|
WSPort: DefaultWSPort,
|
||||||
|
MaxPeers: DefaultMaxPeers,
|
||||||
|
MaxPendingPeers: DefaultMaxPendingPeers,
|
||||||
|
IPCFile: DefaultIPCFile,
|
||||||
|
ChainConfig: &ChainConfig{},
|
||||||
|
LightEthConfig: &LightEthConfig{
|
||||||
|
DatabaseCache: DefaultDatabaseCache,
|
||||||
|
},
|
||||||
|
WhisperConfig: &WhisperConfig{},
|
||||||
|
SwarmConfig: &SwarmConfig{},
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeConfig.populateChainConfig()
|
||||||
|
|
||||||
|
return nodeConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// populateChainConfig does necessary adjustments to config object (depending on network node will be runnin on)
|
||||||
|
func (c *NodeConfig) populateChainConfig() {
|
||||||
|
c.TestNet = false
|
||||||
|
if c.NetworkId == TestNetworkId {
|
||||||
|
c.TestNet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.TestNet {
|
||||||
|
// Homestead fork
|
||||||
|
c.ChainConfig.HomesteadBlock = params.TestnetChainConfig.HomesteadBlock
|
||||||
|
|
||||||
|
// DAO fork
|
||||||
|
c.ChainConfig.DAOForkBlock = params.TestnetChainConfig.DAOForkBlock
|
||||||
|
c.ChainConfig.DAOForkSupport = params.TestnetChainConfig.DAOForkSupport
|
||||||
|
|
||||||
|
// DoS reprice fork
|
||||||
|
c.ChainConfig.EIP150Block = params.TestnetChainConfig.EIP150Block
|
||||||
|
c.ChainConfig.EIP150Hash = params.TestnetChainConfig.EIP150Hash
|
||||||
|
|
||||||
|
// DoS state cleanup fork
|
||||||
|
c.ChainConfig.EIP155Block = params.TestnetChainConfig.EIP155Block
|
||||||
|
c.ChainConfig.EIP158Block = params.TestnetChainConfig.EIP158Block
|
||||||
|
c.ChainConfig.ChainId = params.TestnetChainConfig.ChainId
|
||||||
|
|
||||||
|
if len(c.DataDir) > 0 {
|
||||||
|
c.DataDir = filepath.Join(c.DataDir, "testnet")
|
||||||
|
}
|
||||||
|
c.Genesis = core.DefaultTestnetGenesisBlock()
|
||||||
|
} else {
|
||||||
|
// Homestead fork
|
||||||
|
c.ChainConfig.HomesteadBlock = params.MainNetHomesteadBlock
|
||||||
|
// DAO fork
|
||||||
|
c.ChainConfig.DAOForkBlock = params.MainNetDAOForkBlock
|
||||||
|
c.ChainConfig.DAOForkSupport = true
|
||||||
|
|
||||||
|
// DoS reprice fork
|
||||||
|
c.ChainConfig.EIP150Block = params.MainNetHomesteadGasRepriceBlock
|
||||||
|
c.ChainConfig.EIP150Hash = params.MainNetHomesteadGasRepriceHash
|
||||||
|
|
||||||
|
// DoS state cleanup fork
|
||||||
|
c.ChainConfig.EIP155Block = params.MainNetSpuriousDragon
|
||||||
|
c.ChainConfig.EIP158Block = params.MainNetSpuriousDragon
|
||||||
|
c.ChainConfig.ChainId = params.MainNetChainID
|
||||||
|
|
||||||
|
c.Genesis = core.DefaultGenesisBlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadNodeConfig parses incoming JSON and returned it as Config
|
||||||
|
func LoadNodeConfig(configJSON string) (*NodeConfig, error) {
|
||||||
|
nodeConfig, err := NewNodeConfig("", 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(strings.NewReader(configJSON))
|
||||||
|
//decoder.UseNumber()
|
||||||
|
|
||||||
|
// override default configuration with values by JSON input
|
||||||
|
if err := decoder.Decode(&nodeConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// repopulate
|
||||||
|
nodeConfig.populateChainConfig()
|
||||||
|
|
||||||
|
if len(nodeConfig.DataDir) == 0 {
|
||||||
|
return nil, ErrMissingDataDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.NetworkId <= 0 {
|
||||||
|
return nil, ErrMissingNetworkId
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save dumps configuration to the disk
|
||||||
|
func (c *NodeConfig) Save() error {
|
||||||
|
data, err := json.MarshalIndent(c, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(c.DataDir, os.ModePerm); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
configFilePath := filepath.Join(c.DataDir, "config.json")
|
||||||
|
if err := ioutil.WriteFile(configFilePath, data, os.ModePerm); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(logger.Info).Infof("config file saved: %v", configFilePath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String dumps config object as nicely indented JSON
|
||||||
|
func (c *NodeConfig) String() string {
|
||||||
|
data, _ := json.MarshalIndent(c, "", " ")
|
||||||
|
return string(data)
|
||||||
|
}
|
|
@ -0,0 +1,319 @@
|
||||||
|
package params_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/geth"
|
||||||
|
"github.com/status-im/status-go/geth/params"
|
||||||
|
gethparams "github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
var loadConfigTestCases = []struct {
|
||||||
|
name string
|
||||||
|
configJSON string
|
||||||
|
validator func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
`invalid input configuration`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 3
|
||||||
|
"DataDir": "$TMPDIR",
|
||||||
|
"Name": "TestStatusNode",
|
||||||
|
"WSPort": 8546,
|
||||||
|
"IPCEnabled": true,
|
||||||
|
"WSEnabled": false,
|
||||||
|
"LightEthConfig": {
|
||||||
|
"DatabaseCache": 64
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("error is expected, not thrown")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`missing required field (DataDir)`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 3,
|
||||||
|
"Name": "TestStatusNode"
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err != params.ErrMissingDataDir {
|
||||||
|
t.Fatalf("expected error not thrown, expected: %v, thrown: %v", params.ErrMissingDataDir, err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`missing required field (NetworkId)`,
|
||||||
|
`{
|
||||||
|
"DataDir": "$TMPDIR"
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err != params.ErrMissingNetworkId {
|
||||||
|
t.Fatalf("expected error not thrown, expected: %v, thrown: %v", params.ErrMissingNetworkId, err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`testnet subdirectory not used (while we are on Network = 3)`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 3,
|
||||||
|
"DataDir": "$TMPDIR"
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if nodeConfig.DataDir != filepath.Join(dataDir, "testnet") {
|
||||||
|
t.Fatal("'testnet' subdirectory not used")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(nodeConfig.LightEthConfig.Genesis, "\"chainId\": 3") {
|
||||||
|
t.Fatal("wrong genesis")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`testnet subdirectory used (while we are on Network != 3)`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 1,
|
||||||
|
"DataDir": "$TMPDIR"
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if nodeConfig.DataDir != dataDir {
|
||||||
|
t.Fatal("'testnet' subdirectory used")
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(nodeConfig.LightEthConfig.Genesis, "\"chainId\": 3") {
|
||||||
|
t.Fatal("wrong genesis")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`test parameter overriding`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 3,
|
||||||
|
"DataDir": "$TMPDIR",
|
||||||
|
"Name": "TestStatusNode",
|
||||||
|
"WSPort": 4242,
|
||||||
|
"IPCEnabled": true,
|
||||||
|
"WSEnabled": false,
|
||||||
|
"LightEthConfig": {
|
||||||
|
"DatabaseCache": 64
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.NetworkId != 3 {
|
||||||
|
t.Fatal("wrong NetworkId")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.Name != "TestStatusNode" {
|
||||||
|
t.Fatal("wrong Name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.HTTPPort != params.DefaultHTTPPort {
|
||||||
|
t.Fatal("wrong HTTPPort")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.HTTPHost != params.DefaultHTTPHost {
|
||||||
|
t.Fatal("wrong HTTPHost")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.WSPort != 4242 {
|
||||||
|
t.Fatal("wrong WSPort")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.WSEnabled != false {
|
||||||
|
t.Fatal("wrong WSEnabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.IPCEnabled != true{
|
||||||
|
t.Fatal("wrong IPCEnabled")
|
||||||
|
}
|
||||||
|
if nodeConfig.LightEthConfig.DatabaseCache != 64 {
|
||||||
|
t.Fatal("wrong LightEthConfig.DatabaseCache")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`test loading Testnet config`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 3,
|
||||||
|
"DataDir": "$TMPDIR",
|
||||||
|
"Name": "TestStatusNode",
|
||||||
|
"WSPort": 8546,
|
||||||
|
"IPCEnabled": true,
|
||||||
|
"WSEnabled": false,
|
||||||
|
"LightEthConfig": {
|
||||||
|
"DatabaseCache": 64
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
chainConfig := nodeConfig.ChainConfig
|
||||||
|
refChainConfig := gethparams.TestnetChainConfig
|
||||||
|
|
||||||
|
if chainConfig.HomesteadBlock.Cmp(refChainConfig.HomesteadBlock) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.HomesteadBlock")
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkBlock != nil { // already forked
|
||||||
|
t.Fatal("invalid chainConfig.DAOForkBlock")
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkSupport != refChainConfig.DAOForkSupport {
|
||||||
|
t.Fatal("invalid chainConfig.DAOForkSupport")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Block.Cmp(refChainConfig.EIP150Block) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.EIP150Block")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Hash != refChainConfig.EIP150Hash {
|
||||||
|
t.Fatal("invalid chainConfig.EIP150Hash")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP155Block.Cmp(refChainConfig.EIP155Block) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.EIP155Block")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP158Block.Cmp(refChainConfig.EIP158Block) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.EIP158Block")
|
||||||
|
}
|
||||||
|
if chainConfig.ChainId.Cmp(refChainConfig.ChainId) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.ChainId")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`test loading Mainnet config`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 1,
|
||||||
|
"DataDir": "$TMPDIR",
|
||||||
|
"Name": "TestStatusNode",
|
||||||
|
"WSPort": 8546,
|
||||||
|
"IPCEnabled": true,
|
||||||
|
"WSEnabled": false,
|
||||||
|
"LightEthConfig": {
|
||||||
|
"DatabaseCache": 64
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
chainConfig := nodeConfig.ChainConfig
|
||||||
|
if chainConfig.HomesteadBlock.Cmp(gethparams.MainNetHomesteadBlock) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.HomesteadBlock")
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkBlock.Cmp(gethparams.MainNetDAOForkBlock) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.DAOForkBlock")
|
||||||
|
}
|
||||||
|
if chainConfig.DAOForkSupport != true {
|
||||||
|
t.Fatal("invalid chainConfig.DAOForkSupport")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Block.Cmp(gethparams.MainNetHomesteadGasRepriceBlock) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.EIP150Block")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP150Hash != gethparams.MainNetHomesteadGasRepriceHash {
|
||||||
|
t.Fatal("invalid chainConfig.EIP150Hash")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP155Block.Cmp(gethparams.MainNetSpuriousDragon) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.EIP155Block")
|
||||||
|
}
|
||||||
|
if chainConfig.EIP158Block.Cmp(gethparams.MainNetSpuriousDragon) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.EIP158Block")
|
||||||
|
}
|
||||||
|
if chainConfig.ChainId.Cmp(gethparams.MainNetChainID) != 0 {
|
||||||
|
t.Fatal("invalid chainConfig.ChainId")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`test loading Privatenet config`,
|
||||||
|
`{
|
||||||
|
"NetworkId": 311,
|
||||||
|
"DataDir": "$TMPDIR",
|
||||||
|
"Name": "TestStatusNode",
|
||||||
|
"WSPort": 8546,
|
||||||
|
"IPCEnabled": true,
|
||||||
|
"WSEnabled": false,
|
||||||
|
"ChainConfig": {
|
||||||
|
"ChainId": 311
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||||
|
//nodeConfig.LightEthConfig.Genesis = nodeConfig.LightEthConfig.Genesis[:125]
|
||||||
|
//fmt.Println(nodeConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
networkId := 311
|
||||||
|
|
||||||
|
if nodeConfig.NetworkId != networkId {
|
||||||
|
t.Fatalf("unexpected NetworkId, expected: %v, got: %v", networkId, nodeConfig.NetworkId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeConfig.ChainId.Int64() != int64(networkId) {
|
||||||
|
t.Fatalf("unexpected ChainConfig.ChainId, expected: %v, got: %v", networkId, nodeConfig.ChainId)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadNodeConfig(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir(os.TempDir(), "geth-config-tests")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
for _, testCase := range loadConfigTestCases {
|
||||||
|
t.Log("test: " + testCase.name)
|
||||||
|
testCase.configJSON = strings.Replace(testCase.configJSON, "$TMPDIR", tmpDir, -1)
|
||||||
|
nodeConfig, err := params.LoadNodeConfig(testCase.configJSON)
|
||||||
|
testCase.validator(t, tmpDir, nodeConfig, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigWriteRead(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir(os.TempDir(), "geth-config-tests")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
nodeConfig, err := params.NewNodeConfig(tmpDir, params.TestNetworkId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("cannot create new config object: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := nodeConfig.Save(); err != nil {
|
||||||
|
t.Fatalf("cannot persist configuration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
loadedConfigData, err := ioutil.ReadFile(filepath.Join(nodeConfig.DataDir, "config.json"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("cannot read configuration from disk: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
refConfigData := geth.LoadFromFile("testdata/config.testnet.json")
|
||||||
|
|
||||||
|
refConfigData = strings.Replace(refConfigData, "$TMPDIR", nodeConfig.DataDir, -1)
|
||||||
|
refConfigData = strings.Replace(refConfigData, "$VERSION", params.Version, -1)
|
||||||
|
if string(loadedConfigData) != refConfigData {
|
||||||
|
t.Fatalf("configuration mismatch,\nexpected: %v\ngot: %v", refConfigData, string(loadedConfigData))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultClientIdentifier is client identifier to advertise over the network
|
||||||
|
DefaultClientIdentifier = "status"
|
||||||
|
|
||||||
|
// DefaultIPCFile is filename of exposed IPC RPC Server
|
||||||
|
DefaultIPCFile = "geth.ipc"
|
||||||
|
|
||||||
|
// DefaultHTTPHost is host interface for the HTTP RPC server
|
||||||
|
DefaultHTTPHost = "localhost"
|
||||||
|
|
||||||
|
// DefaultHTTPPort is HTTP-RPC port (replaced in unit tests)
|
||||||
|
DefaultHTTPPort = 8545
|
||||||
|
|
||||||
|
// DefaultAPIModules is a list of modules to expose vie HTTP RPC
|
||||||
|
// TODO remove "admin" on main net
|
||||||
|
DefaultAPIModules = "db,eth,net,web3,shh,personal,admin"
|
||||||
|
|
||||||
|
// DefaultWSHost is a host interface for the websocket RPC server
|
||||||
|
DefaultWSHost = "localhost"
|
||||||
|
|
||||||
|
// DefaultWSPort is a WS-RPC port (replaced in unit tests)
|
||||||
|
DefaultWSPort = 8546
|
||||||
|
|
||||||
|
// DefaultMaxPeers is the maximum number of global peers
|
||||||
|
DefaultMaxPeers = 25
|
||||||
|
|
||||||
|
// DefaultMaxPendingPeers is the maximum number of peers that can be pending in the
|
||||||
|
// handshake phase, counted separately for inbound and outbound connections.
|
||||||
|
DefaultMaxPendingPeers = 0
|
||||||
|
|
||||||
|
// DefaultGas default amount of gas used for transactions
|
||||||
|
DefaultGas = 180000
|
||||||
|
|
||||||
|
// DefaultFileDescriptorLimit is fd limit that database can use
|
||||||
|
DefaultFileDescriptorLimit = uint64(2048)
|
||||||
|
|
||||||
|
// DefaultDatabaseCache is memory (in MBs) allocated to internal caching (min 16MB / database forced)
|
||||||
|
DefaultDatabaseCache = 128
|
||||||
|
|
||||||
|
// TestNetworkId is id of a test network
|
||||||
|
TestNetworkId = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Gas price settings
|
||||||
|
var (
|
||||||
|
GasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon) // Minimal gas price to accept for mining a transactions
|
||||||
|
GpoMinGasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon) // Minimum suggested gas price
|
||||||
|
GpoMaxGasPrice = new(big.Int).Mul(big.NewInt(500), common.Shannon) // Maximum suggested gas price
|
||||||
|
GpoFullBlockRatio = 80 // Full block threshold for gas price calculation (%)
|
||||||
|
GpobaseStepDown = 10 // Suggested gas price base step down ratio (1/1000)
|
||||||
|
GpobaseStepUp = 100 // Suggested gas price base step up ratio (1/1000)
|
||||||
|
GpobaseCorrectionFactor = 110 // Suggested gas price base correction factor (%)
|
||||||
|
)
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/les/status"
|
"github.com/ethereum/go-ethereum/les/status"
|
||||||
"github.com/status-im/status-go/geth"
|
"github.com/status-im/status-go/geth"
|
||||||
|
"github.com/status-im/status-go/geth/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestQueuedContracts(t *testing.T) {
|
func TestQueuedContracts(t *testing.T) {
|
||||||
|
@ -95,7 +96,7 @@ func TestQueuedContracts(t *testing.T) {
|
||||||
From: geth.FromAddress(testConfig.Account1.Address),
|
From: geth.FromAddress(testConfig.Account1.Address),
|
||||||
To: nil, // marker, contract creation is expected
|
To: nil, // marker, contract creation is expected
|
||||||
//Value: (*hexutil.Big)(new(big.Int).Mul(big.NewInt(1), common.Ether)),
|
//Value: (*hexutil.Big)(new(big.Int).Mul(big.NewInt(1), common.Ether)),
|
||||||
Gas: (*hexutil.Big)(big.NewInt(geth.DefaultGas)),
|
Gas: (*hexutil.Big)(big.NewInt(params.DefaultGas)),
|
||||||
Data: byteCode,
|
Data: byteCode,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/status-im/status-go/geth/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -177,14 +178,14 @@ func PrepareTestNode() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// start geth node and wait for it to initialize
|
// start geth node and wait for it to initialize
|
||||||
err = CreateAndRunNode(&NodeConfig{
|
config, err := params.NewNodeConfig(TestDataDir, params.TestNetworkId)
|
||||||
DataDir: TestDataDir,
|
if err != nil {
|
||||||
IPCEnabled: false,
|
return err
|
||||||
HTTPPort: testConfig.Node.HTTPPort, // to avoid conflicts with running app, using different port in tests
|
}
|
||||||
WSEnabled: false,
|
config.HTTPPort = testConfig.Node.HTTPPort // to avoid conflicts with running app, using different port in tests
|
||||||
WSPort: testConfig.Node.WSPort, // ditto
|
config.WSPort = testConfig.Node.WSPort // ditto
|
||||||
TLSEnabled: false,
|
|
||||||
})
|
err = CreateAndRunNode(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue