Skip to content

Commit

Permalink
refactor Parlia implement
Browse files Browse the repository at this point in the history
  • Loading branch information
unclezoro committed May 20, 2020
1 parent 292b48e commit 4fb5e5d
Show file tree
Hide file tree
Showing 29 changed files with 634 additions and 149 deletions.
1 change: 1 addition & 0 deletions accounts/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
MimetypeDataWithValidator = "data/validator"
MimetypeTypedData = "data/typed"
MimetypeClique = "application/x-clique-header"
MimetypeParlia = "application/x-parlia-header"
MimetypeTextPlain = "text/plain"
)

Expand Down
6 changes: 3 additions & 3 deletions accounts/external/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, d
hexutil.Encode(data)); err != nil {
return nil, err
}
// If V is on 27/28-form, convert to to 0/1 for Clique
if mimeType == accounts.MimetypeClique && (res[64] == 27 || res[64] == 28) {
res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use
// If V is on 27/28-form, convert to to 0/1 for Clique and Parlia
if (mimeType == accounts.MimetypeClique || mimeType == accounts.MimetypeParlia) && (res[64] == 27 || res[64] == 28) {
res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique and Parlia use
}
return res, nil
}
Expand Down
114 changes: 114 additions & 0 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ package main
import (
"encoding/json"
"fmt"
"net"
"os"
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync/atomic"
"time"

Expand All @@ -36,6 +39,8 @@ import (
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/trie"
"gopkg.in/urfave/cli.v1"
Expand All @@ -56,6 +61,23 @@ The init command initializes a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be
participating.
It expects the genesis file as argument.`,
}
initNetworkCommand = cli.Command{
Action: utils.MigrateFlags(initNetwork),
Name: "init-network",
Usage: "Bootstrap and initialize a new genesis block, and nodekey, config files for network nodes",
ArgsUsage: "<genesisPath>",
Flags: []cli.Flag{
utils.InitNetworkDir,
utils.InitNetworkPort,
utils.InitNetworkSize,
utils.InitNetworkIps,
configFileFlag,
},
Category: "BLOCKCHAIN COMMANDS",
Description: `
The init-network command initializes a new genesis block, definition for the network, config files for network nodes.
It expects the genesis file as argument.`,
}
dumpGenesisCommand = cli.Command{
Expand Down Expand Up @@ -252,6 +274,98 @@ func initGenesis(ctx *cli.Context) error {
return nil
}

// initNetwork will bootstrap and initialize a new genesis block, and nodekey, config files for network nodes
func initNetwork(ctx *cli.Context) error {
initDir := ctx.String(utils.InitNetworkDir.Name)
if len(initDir) == 0 {
utils.Fatalf("init.dir is required")
}
size := ctx.Int(utils.InitNetworkSize.Name)
port := ctx.Int(utils.InitNetworkPort.Name)
ipStr := ctx.String(utils.InitNetworkIps.Name)
cfgFile := ctx.String(configFileFlag.Name)

if len(cfgFile) == 0 {
utils.Fatalf("config file is required")
}
var ips []string
if len(ipStr) != 0 {
ips = strings.Split(ipStr, ",")
if len(ips) != size {
utils.Fatalf("mismatch of size and length of ips")
}
for i := 0; i < size; i++ {
_, err := net.ResolveIPAddr("", ips[i])
if err != nil {
utils.Fatalf("invalid format of ip")
return err
}
}
} else {
ips = make([]string, size)
for i := 0; i < size; i++ {
ips[i] = "127.0.0.1"
}
}

// Make sure we have a valid genesis JSON
genesisPath := ctx.Args().First()
if len(genesisPath) == 0 {
utils.Fatalf("Must supply path to genesis JSON file")
}
file, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("Failed to read genesis file: %v", err)
}
defer file.Close()

genesis := new(core.Genesis)
if err := json.NewDecoder(file).Decode(genesis); err != nil {
utils.Fatalf("invalid genesis file: %v", err)
}
enodes := make([]*enode.Node, size)

// load config
var config gethConfig
err = loadConfig(cfgFile, &config)
if err != nil {
return err
}
config.Eth.Genesis = genesis

for i := 0; i < size; i++ {
stack, err := node.New(&config.Node)
if err != nil {
return err
}
stack.Config().DataDir = path.Join(initDir, fmt.Sprintf("node%d", i))
pk := stack.Config().NodeKey()
enodes[i] = enode.NewV4(&pk.PublicKey, net.ParseIP(ips[i]), port, port)
}

for i := 0; i < size; i++ {
config.Node.HTTPHost = ips[i]
config.Node.P2P.StaticNodes = make([]*enode.Node, size-1)
for j := 0; j < i; j++ {
config.Node.P2P.StaticNodes[j] = enodes[j]
}
for j := i + 1; j < size; j++ {
config.Node.P2P.StaticNodes[j-1] = enodes[j]
}
out, err := tomlSettings.Marshal(config)
if err != nil {
return err
}
dump, err := os.OpenFile(path.Join(initDir, fmt.Sprintf("node%d", i), "config.toml"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer dump.Close()
dump.Write(out)
}
return nil
}

func dumpGenesis(ctx *cli.Context) error {
genesis := utils.MakeGenesis(ctx)
if genesis == nil {
Expand Down
3 changes: 2 additions & 1 deletion cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,11 @@ func init() {
// Initialize the CLI app and start Geth
app.Action = geth
app.HideVersion = true // we have a command to print the version
app.Copyright = "Copyright 2013-2020 The go-ethereum Authors"
app.Copyright = "Copyright 2013-2020 The go-ethereum Authors and BSC Authors"
app.Commands = []cli.Command{
// See chaincmd.go:
initCommand,
initNetworkCommand,
importCommand,
exportCommand,
importPreimagesCommand,
Expand Down
13 changes: 7 additions & 6 deletions cmd/geth/retesteth.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,26 +229,27 @@ func (e *NoRewardEngine) accumulateRewards(config *params.ChainConfig, state *st
state.AddBalance(header.Coinbase, reward)
}

func (e *NoRewardEngine) Finalize(chain consensus.ChainReader, header *types.Header, statedb *state.StateDB, txs []*types.Transaction,
uncles []*types.Header) {
func (e *NoRewardEngine) Finalize(chain consensus.ChainReader, header *types.Header, statedb *state.StateDB, txs *[]*types.Transaction,
uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) (err error) {
if e.rewardsOn {
e.inner.Finalize(chain, header, statedb, txs, uncles)
err = e.inner.Finalize(chain, header, statedb, txs, uncles, receipts, systemTxs, usedGas)
} else {
e.accumulateRewards(chain.Config(), statedb, header, uncles)
header.Root = statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number))
}
return
}

func (e *NoRewardEngine) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, statedb *state.StateDB, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
if e.rewardsOn {
return e.inner.FinalizeAndAssemble(chain, header, statedb, txs, uncles, receipts)
} else {
e.accumulateRewards(chain.Config(), statedb, header, uncles)
header.Root = statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number))

// Header seems complete, assemble into a block and return
return types.NewBlock(header, txs, uncles, receipts), nil
return types.NewBlock(header, txs, uncles, receipts), receipts, nil
}
}

Expand Down Expand Up @@ -546,7 +547,7 @@ func (api *RetestethAPI) mineBlock() error {
}
}
}
block, err := api.engine.FinalizeAndAssemble(api.blockchain, header, statedb, txs, []*types.Header{}, receipts)
block, _, err := api.engine.FinalizeAndAssemble(api.blockchain, header, statedb, txs, []*types.Header{}, receipts)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
var AppHelpTemplate = `NAME:
{{.App.Name}} - {{.App.Usage}}
Copyright 2013-2019 The go-ethereum Authors
Copyright 2013-2019 The go-ethereum Authors and BSC Authors
USAGE:
{{.App.HelpName}} [options]{{if .App.Commands}} command [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}}
Expand Down
25 changes: 25 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,31 @@ var (
Usage: "External EVM configuration (default = built-in interpreter)",
Value: "",
}

// Init network
InitNetworkSize = cli.IntFlag{
Name: "init.size",
Usage: "the size of the network",
Value: 1,
}

InitNetworkDir = cli.StringFlag{
Name: "init.dir",
Usage: "the direction to store initial network data",
Value: "",
}

InitNetworkIps= cli.StringFlag{
Name: "init.ips",
Usage: "the ips of each node in the network, example '192.168.0.1,192.168.0.2'",
Value: "",
}

InitNetworkPort= cli.IntFlag{
Name: "init.p2p-port",
Usage: "the p2p port of the nodes in the network",
Value: 30311,
}
)

// MakeDataDir retrieves the currently requested data directory, terminating
Expand Down
9 changes: 6 additions & 3 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,21 +552,24 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro

// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
// rewards given.
func (c *Clique) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
func (c *Clique) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header,
receipts *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64) (err error) {
// No block rewards in PoA, so the state remains as is and uncles are dropped
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
header.UncleHash = types.CalcUncleHash(nil)
return
}

// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB,
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
// No block rewards in PoA, so the state remains as is and uncles are dropped
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
header.UncleHash = types.CalcUncleHash(nil)

// Assemble and return the final block for sealing
return types.NewBlock(header, txs, nil, receipts), nil
return types.NewBlock(header, txs, nil, receipts), receipts, nil
}

// Authorize injects a private key into the consensus engine to mint new blocks
Expand Down
17 changes: 14 additions & 3 deletions consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import (
"github.com/ethereum/go-ethereum/rpc"
)

var (
SystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
)

// ChainReader defines a small collection of methods needed to access the local
// blockchain during header and/or uncle verification.
type ChainReader interface {
Expand Down Expand Up @@ -84,16 +88,16 @@ type Engine interface {
//
// Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards).
Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
uncles []*types.Header)
Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction,
uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error

// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
// rewards) and assembles the final block.
//
// Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards).
FinalizeAndAssemble(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error)
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error)

// Seal generates a new sealing request for the given input block and pushes
// the result into the given channel.
Expand Down Expand Up @@ -123,3 +127,10 @@ type PoW interface {
// Hashrate returns the current mining hashrate of a PoW consensus engine.
Hashrate() float64
}

type PoSA interface {
Engine

IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error)
IsSystemContract(to *common.Address) bool
}
9 changes: 6 additions & 3 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,21 +569,24 @@ func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header)

// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
// setting the final state on the header
func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header,
receipts *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64) (err error) {
// Accumulate any block and uncle rewards and commit the final state root
accumulateRewards(chain.Config(), state, header, uncles)
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
return
}

// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
// uncle rewards, setting the final state and assembling the block.
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB,
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
// Accumulate any block and uncle rewards and commit the final state root
accumulateRewards(chain.Config(), state, header, uncles)
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))

// Header seems complete, assemble into a block and return
return types.NewBlock(header, txs, uncles, receipts), nil
return types.NewBlock(header, txs, uncles, receipts), receipts, nil
}

// SealHash returns the hash of a block prior to it being sealed.
Expand Down
7 changes: 5 additions & 2 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
package core

import (
"encoding/json"
"fmt"
"os"

"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state"
Expand Down Expand Up @@ -96,6 +98,7 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
// Validate the state root against the received state root and throw
// an error if they don't match.
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
statedb.IterativeDump(true, true, true, json.NewEncoder(os.Stdout))
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
}
return nil
Expand All @@ -106,10 +109,10 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
// ceil if the blocks are full. If the ceil is exceeded, it will always decrease
// the gas allowance.
func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {
// contrib = (parentGasUsed * 3 / 2) / 1024
// contrib = (parentGasUsed * 3 / 2) / 256
contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor

// decay = parentGasLimit / 1024 -1
// decay = parentGasLimit / 256 -1
decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1

/*
Expand Down
Loading

0 comments on commit 4fb5e5d

Please sign in to comment.