Skip to content

Commit

Permalink
Feat/musicoin (ethereum#81)
Browse files Browse the repository at this point in the history
Adds support for --musicoin chain configuration defaults.
  • Loading branch information
whilei authored May 24, 2019
2 parents 813b4dc + f5da863 commit b5dedaa
Show file tree
Hide file tree
Showing 14 changed files with 337 additions and 4 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Upstream development from [ethereum/go-ethereum](https://github.com/ethereum/go-

Networks supported by the respective go-ethereum packaged `geth` client.

| Ticker | Network/Client | multi-geth | [ethereumclassic/go-ethereum](https://github.com/ethereumclassic/go-ethereum) | [ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) |
| Ticker | Network/Client | multi-geth | [ethereumclassic/go-ethereum](https://github.com/ethereumclassic/go-ethereum) | [ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) |
| --- | --- | --- | --- | --- |
| ETH | Ethereum (Foundation) | :heavy_check_mark: | | :heavy_check_mark: |
| ETC | Ethereum Classic | :heavy_check_mark: | :heavy_check_mark: | |
Expand All @@ -30,7 +30,7 @@ Networks supported by the respective go-ethereum packaged `geth` client.
| MIX | Mix | :heavy_check_mark: | | |
| EXP | Expanse | | | |
| ELLA | Ellaism | :no_entry_sign:<sup>[1](#ellaism-footnote)</sup> | | |
| MUSIC | Musicoin | | | |
| MUSIC | Musicoin | :heavy_check_mark: | | |
| | Morden (Geth+Parity ETH PoW Testnet) | | :heavy_check_mark: | |
| | Ropsten (Geth+Parity ETH PoW Testnet) | :heavy_check_mark: | | :heavy_check_mark: |
| | Rinkeby (Geth-only ETH PoA Testnet) | :heavy_check_mark: | | :heavy_check_mark: |
Expand Down
1 change: 1 addition & 0 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ The export-preimages command export hash preimages to an RLP encoded stream`,
utils.ClassicFlag,
utils.SocialFlag,
utils.EthersocialFlag,
utils.MusicoinFlag,
utils.RinkebyFlag,
utils.KottiFlag,
},
Expand Down
2 changes: 2 additions & 0 deletions cmd/geth/consolecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ func remoteConsole(ctx *cli.Context) error {
path = filepath.Join(path, "mix")
} else if ctx.GlobalBool(utils.EthersocialFlag.Name) {
path = filepath.Join(path, "ethersocial")
} else if ctx.GlobalBool(utils.MusicoinFlag.Name) {
path = filepath.Join(path, "musicoin")
}
}
endpoint = fmt.Sprintf("%s/geth.ipc", path)
Expand Down
1 change: 1 addition & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ var (
utils.SocialFlag,
utils.MixFlag,
utils.EthersocialFlag,
utils.MusicoinFlag,
utils.RinkebyFlag,
utils.KottiFlag,
utils.GoerliFlag,
Expand Down
1 change: 1 addition & 0 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.SocialFlag,
utils.MixFlag,
utils.EthersocialFlag,
utils.MusicoinFlag,
utils.RinkebyFlag,
utils.KottiFlag,
utils.GoerliFlag,
Expand Down
22 changes: 21 additions & 1 deletion cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ var (
Name: "ethersocial",
Usage: "Ethersocial network: pre-configured Ethersocial mainnet",
}
MusicoinFlag = cli.BoolFlag{
Name: "musicoin",
Usage: "Musicoin network: pre-configured Musicoin mainnet",
}
RinkebyFlag = cli.BoolFlag{
Name: "rinkeby",
Usage: "Rinkeby network: pre-configured proof-of-authority test network",
Expand Down Expand Up @@ -747,6 +751,9 @@ func MakeDataDir(ctx *cli.Context) string {
if ctx.GlobalBool(EthersocialFlag.Name) {
return filepath.Join(path, "ethersocial")
}
if ctx.GlobalBool(MusicoinFlag.Name) {
return filepath.Join(path, "musicoin")
}
if ctx.GlobalBool(RinkebyFlag.Name) {
return filepath.Join(path, "rinkeby")
}
Expand Down Expand Up @@ -816,6 +823,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
urls = params.MixBootnodes
case ctx.GlobalBool(EthersocialFlag.Name):
urls = params.EthersocialBootnodes
case ctx.GlobalBool(MusicoinFlag.Name):
urls = params.MusicoinBootnodes
case ctx.GlobalBool(RinkebyFlag.Name):
urls = params.RinkebyBootnodes
case ctx.GlobalBool(KottiFlag.Name):
Expand Down Expand Up @@ -1204,6 +1213,8 @@ func setDataDir(ctx *cli.Context, cfg *node.Config) {
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "mix")
case ctx.GlobalBool(EthersocialFlag.Name):
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ethersocial")
case ctx.GlobalBool(MusicoinFlag.Name):
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "musicoin")
case ctx.GlobalBool(RinkebyFlag.Name):
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
case ctx.GlobalBool(KottiFlag.Name):
Expand Down Expand Up @@ -1399,7 +1410,7 @@ func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
// SetEthConfig applies eth-related command line flags to the config.
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
// Avoid conflicting network flags
checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, KottiFlag, GoerliFlag, ClassicFlag, SocialFlag, MixFlag, EthersocialFlag)
checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, KottiFlag, GoerliFlag, ClassicFlag, SocialFlag, MixFlag, EthersocialFlag, MusicoinFlag)
checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")

// Can't use both ephemeral unlocked and external signer
Expand Down Expand Up @@ -1491,6 +1502,13 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
cfg.NetworkId = 1
}
cfg.Genesis = core.DefaultEthersocialGenesisBlock()

case ctx.GlobalBool(MusicoinFlag.Name):
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 7762959
}
cfg.Genesis = core.DefaultMusicoinGenesisBlock()

case ctx.GlobalBool(RinkebyFlag.Name):
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 4
Expand Down Expand Up @@ -1670,6 +1688,8 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
genesis = core.DefaultMixGenesisBlock()
case ctx.GlobalBool(EthersocialFlag.Name):
genesis = core.DefaultEthersocialGenesisBlock()
case ctx.GlobalBool(MusicoinFlag.Name):
genesis = core.DefaultMusicoinGenesisBlock()
case ctx.GlobalBool(RinkebyFlag.Name):
genesis = core.DefaultRinkebyGenesisBlock()
case ctx.GlobalBool(KottiFlag.Name):
Expand Down
46 changes: 46 additions & 0 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ var (
DisinflationRateDivisor = big.NewInt(5) // Disinflation rate divisor for ECIP1017
ExpDiffPeriod = big.NewInt(100000) // Exponential diff period for diff bomb & ECIP1010

// Musicoin
Mcip0BlockReward = new(big.Int).Mul(big.NewInt(314), big.NewInt(1e+18)) // In musicoin code as 'FrontierBlockReward'
Mcip3BlockReward = new(big.Int).Mul(big.NewInt(250), big.NewInt(1e+18))
Mcip8BlockReward = new(big.Int).Mul(big.NewInt(50), big.NewInt(1e+18))
MusicoinUbiBlockReward = new(big.Int).Mul(big.NewInt(50), big.NewInt(1e+18))
MusicoinDevBlockReward = new(big.Int).Mul(big.NewInt(14), big.NewInt(1e+18))
)

// Various error messages to mark blocks invalid. These should be private to
Expand Down Expand Up @@ -589,6 +595,46 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
if config.IsEthersocial(header.Number) {
blockReward = EthersocialBlockReward
}
if config.IsMCIP0(header.Number) {
// Select the correct block reward based on chain progression
blockReward := Mcip0BlockReward
mcip3Reward := Mcip3BlockReward
mcip8Reward := Mcip8BlockReward
ubiReservoir := MusicoinUbiBlockReward
devReservoir := MusicoinDevBlockReward

reward := new(big.Int).Set(blockReward)

if config.IsMCIP8(header.Number) {
state.AddBalance(header.Coinbase, mcip8Reward)
state.AddBalance(common.HexToAddress("0x00eFdd5883eC628983E9063c7d969fE268BBf310"), ubiReservoir)
state.AddBalance(common.HexToAddress("0x00756cF8159095948496617F5FB17ED95059f536"), devReservoir)
blockReward := mcip8Reward
reward := new(big.Int).Set(blockReward)
_ = reward
} else if config.IsMCIP3(header.Number) {
state.AddBalance(header.Coinbase, mcip3Reward)
state.AddBalance(common.HexToAddress("0x00eFdd5883eC628983E9063c7d969fE268BBf310"), ubiReservoir)
state.AddBalance(common.HexToAddress("0x00756cF8159095948496617F5FB17ED95059f536"), devReservoir)
// no change to uncle reward during UBI fork, a mistake but now a legacy
} else {
state.AddBalance(header.Coinbase, reward)
}

// Accumulate the rewards for the miner and any included uncles
r := new(big.Int)
for _, uncle := range uncles {
r.Add(uncle.Number, big8)
r.Sub(r, header.Number)
r.Mul(r, blockReward)
r.Div(r, big8)
state.AddBalance(uncle.Coinbase, r)

r.Div(blockReward, big32)
reward.Add(reward, r)
}
return
}
if config.HasECIP1017() {
// Ensure value 'era' is configured.
eraLen := config.ECIP1017EraRounds
Expand Down
10 changes: 9 additions & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/hashicorp/golang-lru"
lru "github.com/hashicorp/golang-lru"
)

var (
Expand Down Expand Up @@ -1145,6 +1145,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
abort, results := bc.engine.VerifyHeaders(bc, headers, seals)
defer close(abort)

if bc.Config().IsMCIP0(common.Big0) {
musicoinErrChain := bc.checkChainForAttack(chain)
if musicoinErrChain != nil {
log.Error("musicoin rat(s) discovered", "error", musicoinErrChain.Error())
return 0, events, coalescedLogs, musicoinErrChain
}
}

// Peek the error for the first block to decide the directing import logic
it := newInsertIterator(chain, results, bc.validator)

Expand Down
159 changes: 159 additions & 0 deletions core/blockchain_musicoin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

// Package core implements the Ethereum consensus protocol.
package core

import (
"errors"
"sort"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)

// let's defeat the rat(s)

var syncStatus bool
var ErrDelayTooHigh = errors.New("Chain time values are not right!")

func (bc *BlockChain) checkChainForAttack(blocks types.Blocks) error {
// Copyright 2014 The go-ethereum Authors
// Copyright 2018 Pirl Sprl
// This file is part of the go-ethereum library modified with Pirl Security Protocol.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see http://www.gnu.org/licenses/.
// Package core implements the Ethereum consensus protocol modified with Pirl Security Protocol.

err := errors.New("")
err = nil
timeMap := make(map[uint64]int64)
tipOfTheMainChain := bc.CurrentBlock().NumberU64()

if !syncStatus {
if tipOfTheMainChain == blocks[0].NumberU64()-1 {
//fmt.Println("We are synced")
syncStatus = true
} else {
//fmt.Println("Still syncing!")
syncStatus = false
}
}

if len(blocks) > 0 && bc.CurrentBlock().NumberU64() > uint64(params.MusicoinTimeCapsuleBlock) {
if syncStatus && len(blocks) > int(params.MusicoinTimeCapsuleLength) {
for _, b := range blocks {
timeMap[b.NumberU64()] = calculatePenaltyTimeForBlock(tipOfTheMainChain, b.NumberU64())
}
}
}
p := make(PairList, len(timeMap))
index := 0
for k, v := range timeMap {
p[index] = Pair{k, v}
index++
}
sort.Sort(p)
var penalty int64
for _, v := range p {
penalty += v.Value
}

multi := calculateMulti(bc.CurrentBlock().Difficulty().Uint64())
penalty = penalty * int64(multi)

if penalty < 0 {
penalty = 0
}
//fmt.Println("Penalty value for the chain :", penalty)
context := []interface{}{
"synced", syncStatus, "number", tipOfTheMainChain, "incoming_number", blocks[0].NumberU64() - 1, "penalty", penalty, "implementation", "Pirl for $MUSIC",
}

log.Info("checking legitimity of the chain", context...)

if penalty > 0 {
context := []interface{}{
"penalty", penalty,
}
log.Error("Chain is a malicious and we should reject it", context...)
err = ErrDelayTooHigh
}

if penalty == 0 {
err = nil
}

return err
}

func calculatePenaltyTimeForBlock(tipOfTheMainChain, incomingBlock uint64) int64 {
if incomingBlock < tipOfTheMainChain {
return int64(tipOfTheMainChain - incomingBlock)
}
if incomingBlock == tipOfTheMainChain {
return 0
}
if incomingBlock > tipOfTheMainChain {
return -1
}
return 0
}

func calculateMulti(diff uint64) uint64 {

if diff <= 500000000 {
return 5
}
if diff >= 500000000 && diff < 20000000000 {
return 4
}
if diff >= 20000000000 && diff < 30000000000 {
return 3
}
if diff >= 30000000000 && diff < 50000000000 {
return 2
}
if diff >= 50000000000 {
return 1
}
return 1
}

// A data structure to hold key/value pairs
type Pair struct {
Key uint64
Value int64
}

// A slice of pairs that implements sort.Interface to sort by values
type PairList []Pair

func (p PairList) Len() int { return len(p) }
func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p PairList) Less(i, j int) bool { return p[i].Key < p[j].Key }
16 changes: 16 additions & 0 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
return params.MixChainConfig
case ghash == params.EthersocialGenesisHash:
return params.EthersocialChainConfig
case ghash == params.MusicoinGenesisHash:
return params.MusicoinChainConfig
case ghash == params.KottiGenesisHash:
return params.KottiChainConfig
default:
Expand Down Expand Up @@ -371,6 +373,20 @@ func DefaultEthersocialGenesisBlock() *Genesis {
}
}

// MusicoinGenesisBlock returns the Musicoin main net genesis block.
func DefaultMusicoinGenesisBlock() *Genesis {
return &Genesis{
Config: params.MusicoinChainConfig,
Timestamp: 0,
Nonce: 42,
ExtraData: nil,
Mixhash: common.HexToHash("0x00000000000000000000000000000000000000647572616c65787365646c6578"),
GasLimit: 8000000,
Difficulty: big.NewInt(4000000),
Alloc: decodePrealloc(musicoinAllocData),
}
}

// DefaultTestnetGenesisBlock returns the Ropsten network genesis block.
func DefaultTestnetGenesisBlock() *Genesis {
return &Genesis{
Expand Down
1 change: 1 addition & 0 deletions core/genesis_alloc.go

Large diffs are not rendered by default.

Loading

0 comments on commit b5dedaa

Please sign in to comment.