Skip to content

Commit

Permalink
Merge pull request #20 from haloplatform/public_merge
Browse files Browse the repository at this point in the history
CoinSplit
  • Loading branch information
quocneo authored Dec 19, 2018
2 parents 5b47c2b + de295b2 commit 5e51ad3
Show file tree
Hide file tree
Showing 44 changed files with 1,902 additions and 270 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.1
2.2.0
20 changes: 19 additions & 1 deletion cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package main

import (
"bufio"
"crypto/ecdsa"
"errors"
"fmt"
"io"
Expand All @@ -30,6 +31,7 @@ import (
"time"

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/dashboard"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/node"
Expand Down Expand Up @@ -144,6 +146,8 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {

// Set reward value: 38 Halos
params.MasterNodeReward.SetString(params.MasterNodeRewardString, 10)
// Set reward value: 30400 Halos for coin-split hard-fork
params.MasterNodeSplitReward.SetString(params.MasterNodeSplitRewardString, 10)

return stack, cfg
}
Expand Down Expand Up @@ -220,6 +224,20 @@ func RegisterRaftService(stack *node.Node, ctx *cli.Context, cfg gethConfig, eth
maxTxsPerAccount := ctx.GlobalInt(utils.MaxTxsPerAccountFlag.Name)
rewardMinutes := ctx.GlobalInt(utils.RaftRewardTimeFlag.Name)

if !ctx.GlobalIsSet(utils.RaftSignKeyFlag.Name) {
utils.Fatalf("Raft requires sign key, option: %q", utils.RaftSignKeyFlag.Name)
}

var (
file = ctx.GlobalString(utils.RaftSignKeyFlag.Name)
key *ecdsa.PrivateKey
err error
)

if key, err = crypto.LoadECDSA(file); err != nil {
utils.Fatalf("Load ping key file, option %q: %v", utils.RaftSignKeyFlag.Name, err)
}

if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
privkey := cfg.Node.NodeKey()
strId := discover.PubkeyID(&privkey.PublicKey).String()
Expand Down Expand Up @@ -257,7 +275,7 @@ func RegisterRaftService(stack *node.Node, ctx *cli.Context, cfg gethConfig, eth

ethereum := <-ethChan

return raft.New(ctx, ethereum.ChainConfig(), myId, raftPort, joinExisting, blockTimeNanos, electionTick, rewardTime, maxTxsPerBlock, maxTxsPerAccount, ethereum, peers, datadir)
return raft.New(ctx, ethereum.ChainConfig(), myId, raftPort, joinExisting, blockTimeNanos, electionTick, rewardTime, key, maxTxsPerBlock, maxTxsPerAccount, ethereum, peers, datadir)
}); err != nil {
utils.Fatalf("Failed to register the Raft service: %v", err)
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ var (
utils.MNRewardAddrFlag,
utils.PingKeyFlag,
utils.RaftRewardTimeFlag,
utils.RaftSignKeyFlag,
utils.ClientPubKeyFlag,
}

rpcFlags = []cli.Flag{
Expand Down
2 changes: 2 additions & 0 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ var AppHelpFlagGroups = []flagGroup{
// utils.LightServFlag,
// utils.LightPeersFlag,
// utils.LightKDFFlag,
utils.ClientPubKeyFlag,
},
},
// {Name: "DEVELOPER CHAIN",
Expand Down Expand Up @@ -155,6 +156,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.RaftPortFlag,
utils.ElectionTickFlag,
utils.RaftRewardTimeFlag,
utils.RaftSignKeyFlag,
},
},
{
Expand Down
41 changes: 37 additions & 4 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,12 +604,22 @@ var (
Value: 4,
}

RaftSignKeyFlag = cli.StringFlag{
Name: "raftkey",
Usage: "Private key for signing a block",
}

// Quorum
EnableNodePermissionFlag = cli.BoolFlag{
Name: "permissioned",
Usage: "If enabled, the node will allow only a defined list of nodes to connect",
}

ClientPubKeyFlag = cli.StringFlag{
Name: "pubkey",
Usage: "Public key for block validation, hex string",
}

// Masternode
MNInstanceAddrFlag = cli.StringFlag{
Name: "mn",
Expand Down Expand Up @@ -690,8 +700,7 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
} else {
urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
}
case ctx.GlobalBool(TestnetFlag.Name):
case ctx.GlobalUint64(NetworkIdFlag.Name) == params.HaloTestnetNetworkId:
case ctx.GlobalBool(TestnetFlag.Name) || ctx.GlobalUint64(NetworkIdFlag.Name) == params.HaloTestnetNetworkId:
urls = params.TestnetBootnodes
log.Debug("Testnet bootnode", "boot", urls)
// case ctx.GlobalBool(RinkebyFlag.Name):
Expand Down Expand Up @@ -960,7 +969,13 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
cfg.DiscoveryV5 = false
}
/// NetworkID for filtering P2P messages
cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
cfg.NetworkId = params.HaloMainnetNetworkId
if ctx.GlobalIsSet(NetworkIdFlag.Name) {
cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
}
if ctx.GlobalBool(TestnetFlag.Name) {
cfg.NetworkId = params.HaloTestnetNetworkId
}

if ctx.GlobalBool(RaftModeFlag.Name) {
cfg.PeerType = p2p.NODE_TYPE_RAFT
Expand Down Expand Up @@ -997,7 +1012,7 @@ func setMasternodeConfig(ctx *cli.Context, cfg *mn.Config) {

cfg.InstAddr = common.HexToAddress(inst_addr)
cfg.RewardAddr = common.HexToAddress(reward_addr)
cfg.PingInterVal = 10 // Fixed at 10 minutes
cfg.PingInterVal = 60 // Fixed at 60 minutes

if !ctx.GlobalIsSet(PingKeyFlag.Name) {
Fatalf("PING requires private key, option: %q", PingKeyFlag.Name)
Expand All @@ -1024,6 +1039,24 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
setWS(ctx, cfg)
setNodeUserIdent(ctx, cfg)

/// Public key
switch {
// Mainnet
case cfg.P2P.NetworkId == params.HaloMainnetNetworkId:
params.HaloPublicKey = params.HaloMainnetPublicKey
// Testnet
case cfg.P2P.NetworkId == params.HaloTestnetNetworkId:
params.HaloPublicKey = params.HaloTestnetPublicKey
default:
{
// Using the setting from cmd. Otherwise, using the default
if ctx.GlobalIsSet(ClientPubKeyFlag.Name) {
// Validate the hex string in Ethash. Don't do here
params.HaloPublicKey = ctx.GlobalString(ClientPubKeyFlag.Name)
}
}
}

switch {
case ctx.GlobalIsSet(DataDirFlag.Name):
cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
Expand Down
23 changes: 17 additions & 6 deletions consensus/ethash/algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,25 @@ const (
// reused between hash runs instead of requiring new ones to be created.
type hasher func(dest []byte, data []byte)

// makeHasher creates a repetitive hasher, allowing the same hash data structures
// to be reused between hash runs instead of requiring new ones to be created.
// The returned function is not thread safe!
// makeHasher creates a repetitive hasher, allowing the same hash data structures to
// be reused between hash runs instead of requiring new ones to be created. The returned
// function is not thread safe!
func makeHasher(h hash.Hash) hasher {
// sha3.state supports Read to get the sum, use it to avoid the overhead of Sum.
// Read alters the state but we reset the hash before every operation.
type readerHash interface {
hash.Hash
Read([]byte) (int, error)
}
rh, ok := h.(readerHash)
if !ok {
panic("can't find Read method on hash")
}
outputLen := rh.Size()
return func(dest []byte, data []byte) {
h.Write(data)
h.Sum(dest[:0])
h.Reset()
rh.Reset()
rh.Write(data)
rh.Read(dest[:outputLen])
}
}

Expand Down
68 changes: 58 additions & 10 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package ethash

import (
"bytes"
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
Expand All @@ -30,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
set "gopkg.in/fatih/set.v0"
)
Expand Down Expand Up @@ -58,6 +60,7 @@ var (
errInvalidDifficulty = errors.New("non-positive difficulty")
errInvalidMixDigest = errors.New("invalid mix digest")
errInvalidPoW = errors.New("invalid proof-of-work")
errInvalidBlockSig = errors.New("invalid block signature")
)

func mustParseRfc3339(str string) time.Time {
Expand All @@ -77,6 +80,15 @@ func (ethash *Ethash) Author(header *types.Header) (common.Address, error) {
// VerifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum ethash engine.
func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
// Verify block signature in MixHash/MixDigestHash
if chain.Config().IsCoinSplitFork(header.Number) {
// Verify block signature in MixHash/MixDigestHash
res := ValidateSignedHeader(ethash.haloPublicKey, header)
if !res {
return errInvalidBlockSig
}
}

// If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake {
return nil
Expand All @@ -98,14 +110,14 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.He
// concurrently. The method returns a quit channel to abort the operations and
// a results channel to retrieve the async verifications.
func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
// If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake || len(headers) == 0 {
abort, results := make(chan struct{}), make(chan error, len(headers))
for i := 0; i < len(headers); i++ {
results <- nil
}
return abort, results
}
// // If we're running a full engine faking, accept any input as valid
// if ethash.config.PowMode == ModeFullFake || len(headers) == 0 {
// abort, results := make(chan struct{}), make(chan error, len(headers))
// for i := 0; i < len(headers); i++ {
// results <- nil
// }
// return abort, results
// }

// Spawn as many workers as allowed threads
workers := runtime.GOMAXPROCS(0)
Expand Down Expand Up @@ -231,6 +243,19 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
// stock Ethereum ethash engine.
// See YP section 4.3.4. "Block Header Validity"
func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error {
if chain.Config().IsCoinSplitFork(header.Number) {
// Verify block signature in MixHash/MixDigestHash
res := ValidateSignedHeader(ethash.haloPublicKey, header)
if !res {
return errInvalidBlockSig
}
}

// If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake {
return nil
}

// Ensure that the header's extra-data section is of a reasonable size
maximumExtraDataSize := params.GetMaximumExtraDataSize(chain.Config().IsQuorum)
if uint64(len(header.Extra)) > maximumExtraDataSize {
Expand Down Expand Up @@ -265,6 +290,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
if header.Time.Cmp(parent.Time) <= 0 {
return errZeroBlockTime
}

// Verify the block's difficulty based in it's timestamp and parent's difficulty
expected := ethash.CalcDifficulty(chain, header.Time.Uint64(), parent)

Expand Down Expand Up @@ -570,7 +596,29 @@ var (
func AccumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
zeroAddr := common.HexToAddress("0x0000000000000000000000000000000000000000")
if bytes.Compare(zeroAddr.Bytes(), header.Coinbase.Bytes()) != 0 {
// Send to address where masternode rewards are accumulated
state.AddBalance(header.Coinbase, params.MasterNodeReward)
if config.IsCoinSplitFork(header.Number) {
// Add reward after coin-split hard-fork
state.AddBalance(header.Coinbase, params.MasterNodeSplitReward)
} else {
// Send to address where masternode rewards are accumulated
state.AddBalance(header.Coinbase, params.MasterNodeReward)
}
}
}

func SignHeader(privateKey *ecdsa.PrivateKey, header *types.Header) ([]byte, error) {
sig, err := crypto.Sign(header.HashForSign().Bytes(), privateKey)
if sig == nil {
return nil, err
}
return sig, nil
}

func ValidateSignedHeader(publicKey []byte, header *types.Header) (result bool) {
if len(header.Extra) != 65 {
/// Invalid length
return false
}
res := crypto.VerifySignature(publicKey, header.HashForSign().Bytes(), header.Extra[:64])
return res
}
21 changes: 19 additions & 2 deletions consensus/ethash/ethash.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ import (
"unsafe"

mmap "github.com/edsrzf/mmap-go"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/hashicorp/golang-lru/simplelru"
metrics "github.com/rcrowley/go-metrics"
Expand Down Expand Up @@ -408,7 +410,8 @@ type Ethash struct {
fakeFail uint64 // Block number which fails PoW check even in fake mode
fakeDelay time.Duration // Time delay to sleep for before returning from verify

lock sync.Mutex // Ensures thread safety for the in-memory caches and mining fields
lock sync.Mutex // Ensures thread safety for the in-memory caches and mining fields
haloPublicKey []byte // Halo public key for block signature validation
}

// New creates a full sized ethash PoW scheme.
Expand Down Expand Up @@ -476,10 +479,24 @@ func NewFakeDelayer(delay time.Duration) *Ethash {
// NewFullFaker creates an ethash consensus engine with a full fake scheme that
// accepts all blocks as valid, without checking any consensus rules whatsoever.
func NewFullFaker() *Ethash {
pubKey, err := hexutil.Decode(params.HaloPublicKey)
if pubKey == nil {
log.Crit("Invalid Halo public key", "key", params.HaloPublicKey, "err", err)
return nil
}

if len(pubKey) != 65 {
log.Crit("Invalid Halo public key length", "len", len(pubKey), "key", params.HaloPublicKey)
return nil
}

log.Info("Halo public key", "key", params.HaloPublicKey)

return &Ethash{
config: Config{
PowMode: ModeFullFake,
},
haloPublicKey: pubKey,
}
}

Expand Down Expand Up @@ -580,4 +597,4 @@ func SeedHash(block uint64) []byte {
// Protocol implements consensus.Engine.Protocol
func (ethash *Ethash) Protocol() consensus.Protocol {
return consensus.EthProtocol
}
}
Loading

0 comments on commit 5e51ad3

Please sign in to comment.