fix dynamic network id through json rpc

Former-commit-id: 75c1f05973e1fd9cdaa86518c80b39517e0a21d3 [formerly 8279f4fa7f7ee34ad97ae332e281c89a89c5269b]
Former-commit-id: fe4066caab62419df0ca4e33fefb3539b4159335
This commit is contained in:
Raul Jordan
2018-01-21 23:13:20 -06:00
8 changed files with 418 additions and 0 deletions

View File

@@ -164,6 +164,8 @@ func init() {
consoleCommand,
attachCommand,
javascriptCommand,
// See shardingcmd.go:
shardingClientCommand,
// See misccmd.go:
makecacheCommand,
makedagCommand,

32
cmd/geth/shardingcmd.go Normal file
View File

@@ -0,0 +1,32 @@
package main
import (
"github.com/ethereum/go-ethereum/sharding"
"github.com/ethereum/go-ethereum/cmd/utils"
cli "gopkg.in/urfave/cli.v1"
)
var (
shardingClientCommand = cli.Command{
Action: utils.MigrateFlags(shardingClient),
Name: "sharding",
Aliases: []string{"shard"},
Usage: "Start a sharding client",
ArgsUsage: "[endpoint]",
Flags: []cli.Flag{utils.DataDirFlag, utils.PasswordFileFlag, utils.NetworkIdFlag},
Category: "SHARDING COMMANDS",
Description: `
The Geth sharding client connects to a running geth node in sharding mode. This feature is a work in progress.
`,
}
)
func shardingClient(ctx *cli.Context) error {
c := sharding.MakeShardingClient(ctx)
if err := c.Start(); err != nil {
return err
}
c.Wait()
return nil
}

1
password.txt Normal file
View File

@@ -0,0 +1 @@
123456

105
sharding/client.go Normal file
View File

@@ -0,0 +1,105 @@
package sharding
import (
"fmt"
"io/ioutil"
"strings"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
cli "gopkg.in/urfave/cli.v1"
)
const (
clientIdentifier = "geth" // Used to determine the ipc name.
)
// Client for sharding. Communicates to geth node via JSON RPC.
type Client struct {
endpoint string // Endpoint to JSON RPC
client *ethclient.Client // Ethereum RPC client.
keystore *keystore.KeyStore // Keystore containing the single signer
ctx *cli.Context // Command line context
}
// MakeShardingClient for interfacing with geth full node.
func MakeShardingClient(ctx *cli.Context) *Client {
path := node.DefaultDataDir()
if ctx.GlobalIsSet(utils.DataDirFlag.Name) {
path = ctx.GlobalString(utils.DataDirFlag.Name)
}
endpoint := ctx.Args().First()
if endpoint == "" {
endpoint = fmt.Sprintf("%s/%s.ipc", path, clientIdentifier)
}
config := &node.Config{
DataDir: path,
}
scryptN, scryptP, keydir, err := config.AccountConfig()
if err != nil {
panic(err) // TODO(prestonvanloon): handle this
}
ks := keystore.NewKeyStore(keydir, scryptN, scryptP)
return &Client{
endpoint: endpoint,
keystore: ks,
ctx: ctx,
}
}
// Start the sharding client.
// * Connects to node.
// * Verifies or deploys the validator management contract.
func (c *Client) Start() error {
log.Info("Starting sharding client")
rpcClient, err := dialRPC(c.endpoint)
if err != nil {
return err
}
c.client = ethclient.NewClient(rpcClient)
defer rpcClient.Close()
if err := c.verifyVMC(); err != nil {
return err
}
// TODO: Wait to be selected as collator in goroutine?
return nil
}
// Wait until sharding client is shutdown.
func (c *Client) Wait() {
// TODO: Blocking lock.
}
// dialRPC endpoint to node.
func dialRPC(endpoint string) (*rpc.Client, error) {
if endpoint == "" {
endpoint = node.DefaultIPCEndpoint(clientIdentifier)
}
return rpc.Dial(endpoint)
}
// UnlockAccount will unlock the specified account using utils.PasswordFileFlag or empty string if unset.
func (c *Client) unlockAccount(account accounts.Account) error {
pass := ""
if c.ctx.GlobalIsSet(utils.PasswordFileFlag.Name) {
blob, err := ioutil.ReadFile(c.ctx.GlobalString(utils.PasswordFileFlag.Name))
if err != nil {
return fmt.Errorf("unable to read account password contents in file %s. %v", utils.PasswordFileFlag.Value, err)
}
// TODO: Use bufio.Scanner or other reader that doesn't include a trailing newline character.
pass = strings.Trim(string(blob), "\n") // Some text files end in new line, remove with strings.Trim.
}
return c.keystore.Unlock(account, pass)
}

123
sharding/client_test.go Normal file
View File

@@ -0,0 +1,123 @@
package sharding
import (
"context"
"flag"
"fmt"
"math/big"
"math/rand"
"os"
"sync"
"testing"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
cli "gopkg.in/urfave/cli.v1"
)
// FakeEthService based on implementation of internal/ethapi.Client
type FakeEthService struct {
mu sync.Mutex
getCodeResp hexutil.Bytes
getCodeErr error
}
// eth_getCode
func (s *FakeEthService) GetCode(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
s.mu.Lock()
defer s.mu.Unlock()
return s.getCodeResp, s.getCodeErr
}
// Set return values for eth_getCode
func (s *FakeEthService) SetGetCode(resp hexutil.Bytes, err error) {
s.mu.Lock()
s.getCodeResp = resp
s.getCodeErr = err
s.mu.Unlock()
}
func (s *FakeEthService) GasPrice(ctx context.Context) (*big.Int, error) {
return big.NewInt(10000), nil
}
func (s *FakeEthService) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) {
return nil, nil
}
func (s *FakeEthService) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
return common.Hash{}, nil
}
func (s *FakeEthService) GetTransactionReceipt(hash common.Hash) (*types.Receipt, error) {
return &types.Receipt{
ContractAddress: common.StringToAddress("0x1"),
Logs: []*types.Log{},
}, nil
}
func (s *FakeEthService) GetTransactionByHash(hash common.Hash) (tx *types.Transaction, isPending bool, err error) {
return nil, false, nil
}
func newTestServer(endpoint string) (*rpc.Server, error) {
// Create datadir.
if err := os.Mkdir(endpoint, 0777); err != nil {
return nil, err
}
// Create a default account without password.
scryptN, scryptP, keydir, err := (&node.Config{DataDir: endpoint}).AccountConfig()
if err != nil {
return nil, err
}
if _, err := keystore.StoreKey(keydir, "" /*password*/, scryptN, scryptP); err != nil {
return nil, err
}
// Create server and register eth service with FakeEthService
server := rpc.NewServer()
if err := server.RegisterName("eth", new(FakeEthService)); err != nil {
return nil, err
}
l, err := rpc.CreateIPCListener(endpoint + "/geth.ipc")
if err != nil {
return nil, err
}
go server.ServeListener(l)
return server, nil
}
func createContext() *cli.Context {
set := flag.NewFlagSet("test", 0)
set.String(utils.DataDirFlag.Name, "", "")
return cli.NewContext(nil, set, nil)
}
func TestShardingClient(t *testing.T) {
endpoint := fmt.Sprintf("%s/go-ethereum-test-ipc-%d-%d", os.TempDir(), os.Getpid(), rand.Int63())
server, err := newTestServer(endpoint)
if err != nil {
t.Fatalf("Failed to create a test server: %v", err)
}
defer server.Stop()
ctx := createContext()
if err := ctx.GlobalSet(utils.DataDirFlag.Name, endpoint); err != nil {
t.Fatalf("Failed to set global variable for flag %s. Error: %v", utils.DataDirFlag.Name, err)
}
c := MakeShardingClient(ctx)
if err := c.Start(); err != nil {
t.Errorf("Failed to start server: %v", err)
}
}

24
sharding/config.go Normal file
View File

@@ -0,0 +1,24 @@
package sharding
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
)
var (
// Number of network shards
shardCount = 100
// Address of the validator management contract
validatorManagerAddress = common.HexToAddress("0x0") // TODO
// Gas limit for verifying signatures
sigGasLimit = 40000
// Number of blocks in a period
periodLength = 5
// Number of periods ahead of current period which the contract is able to return the collator of that period.
lookaheadPeriods = 4
// Required deposit size in wei
depositSize = new(big.Int).Exp(big.NewInt(10), big.NewInt(20), nil) // 100 ETH
// Gas limit to create contract
contractGasLimit = uint64(4700000) // Max is 4712388
)

16
sharding/config_test.go Normal file
View File

@@ -0,0 +1,16 @@
package sharding
import (
"math/big"
"testing"
)
func TestDepositSize(t *testing.T) {
want, err := new(big.Int).SetString("100000000000000000000", 10) // 100 ETH
if !err {
t.Fatalf("Failed to setup test")
}
if depositSize.Cmp(want) != 0 {
t.Errorf("depositSize incorrect. Wanted %d, got %d", want, depositSize)
}
}

115
sharding/vmc.go Normal file

File diff suppressed because one or more lines are too long