Skip to content

Commit

Permalink
Merge pull request #169 from XinFinOrg/v2-beta
Browse files Browse the repository at this point in the history
- V2 consensus engine
  • Loading branch information
wjrjerome authored Aug 6, 2022
2 parents 7808840 + c1d0b71 commit 22479f1
Show file tree
Hide file tree
Showing 99 changed files with 10,105 additions and 32,480 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,51 @@
# XDPoSChain
## XinFin Hybrid Blockchain

XinFin Hybrid Blockchain is an Enterprise ready Blockchain for global trade and finance

Visit: [XinFin.org](https://xinfin.org)
Contribute: [Developer Docs](https://docs.xinfin.org)

## XinFin Network XDPoS is community driven project to achieve the following

- XinFin DPOS (XDPoS) consensus that selects 108 set of Masternodes to achieve a high throughput Energy efficient consensus with instant block finality

- KYC Enforcement on Masternodes for Enterprise Adoption and compliance

- Ability to port/relay limited set of data and transactions from privacy channels to public channel

- Interoperability between applications hosted on Private Blockchains like Corda, Hyperledger, Quorum(JP Morgan) using relayers to XinFin Network

- Customer Centric and consortium driven Governance to equally benefit the validators as well as providing comfort for large scale enterprise applications to be hosted on the Network. This achieves

- Rapid Upgradability

- DApps Standardisation for rapid commercialisation

- Compliance with major global jurisdictions.

### KYC for masternodes

#### OVERVIEW

To add a layer of KYC for masternodes in the current system and a sense of ownership amongst the masternodes hence tying such a cluster of masternodes to physical entity which can held accountable for its actions.

#### Design

We established a bidirectional connection between a candidate and its owner inorder to retrieve a candidate belonging to a specific owner & vice versa.

All the masternodes are recognized by the KYC of their owners and hence are considered as a single verified entity ( for eg. while voting for invalid KYC, only one vote is considered per such cluster )

The contract is very strict in handing out penalty for invalid KYC, it results loss of all funds invested in all of its candidates.

For eg. say A proposes condidates B,C,D by paying for its proposal cost.
If at a later stage if some predecided amount of owners ( investors ) vote that a KYC for a A is invalid then A & all of its candidates (B,C,D) will lose their position & all their funds will be lost ( will remain with contract wallet ).

### For developers

### To contribute

Simple create a pull request along with proper reasoning, we'll get back to you.

Our Channels : [Telegram Developer Group](https://t.me/XinFinDevelopers) or [Public Slack Group](https://launchpass.com/xinfin-public)

26 changes: 26 additions & 0 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"math/big"
"os"
"sync"
"time"

Expand All @@ -29,7 +31,9 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/rawdb"

"github.com/XinFinOrg/XDPoSChain"
"github.com/XinFinOrg/XDPoSChain/accounts"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
"github.com/XinFinOrg/XDPoSChain/accounts/keystore"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/math"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
Expand Down Expand Up @@ -69,6 +73,28 @@ type SimulatedBackend struct {
config *params.ChainConfig
}

func SimulateWalletAddressAndSignFn() (common.Address, func(account accounts.Account, hash []byte) ([]byte, error), error) {
veryLightScryptN := 2
veryLightScryptP := 1
dir, _ := ioutil.TempDir("", "eth-SimulateWalletAddressAndSignFn-test")

new := func(kd string) *keystore.KeyStore {
return keystore.NewKeyStore(kd, veryLightScryptN, veryLightScryptP)
}

defer os.RemoveAll(dir)
ks := new(dir)
pass := "" // not used but required by API
a1, err := ks.NewAccount(pass)
if err != nil {
return common.Address{}, nil, fmt.Errorf(err.Error())
}
if err := ks.Unlock(a1, ""); err != nil {
return a1.Address, nil, fmt.Errorf(err.Error())
}
return a1.Address, ks.SignHash, nil
}

// XDC simulated backend for testing purpose.
func NewXDCSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64, chainConfig *params.ChainConfig) *SimulatedBackend {
// database := ethdb.NewMemDatabase()
Expand Down
12 changes: 10 additions & 2 deletions cmd/XDC/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ package main
import (
"encoding/json"
"fmt"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"os"
"runtime"
"strconv"
"sync/atomic"
"time"

"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/metrics"

"github.com/XinFinOrg/XDPoSChain/cmd/utils"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/console"
Expand Down Expand Up @@ -207,6 +209,12 @@ func importChain(ctx *cli.Context) error {
if len(ctx.Args()) < 1 {
utils.Fatalf("This command requires an argument.")
}

// Start metrics export if enabled
utils.SetupMetrics(ctx)
// Start system runtime metrics collection
go metrics.CollectProcessMetrics(3 * time.Second)

stack, _ := makeFullNode(ctx)
chain, chainDb := utils.MakeChain(ctx, stack)
defer chainDb.Close()
Expand Down Expand Up @@ -368,7 +376,7 @@ func copyDb(ctx *cli.Context) error {
chain, chainDb := utils.MakeChain(ctx, stack)

syncmode := *utils.GlobalTextMarshaler(ctx, utils.SyncModeFlag.Name).(*downloader.SyncMode)
dl := downloader.New(syncmode, chainDb, new(event.TypeMux), chain, nil, nil)
dl := downloader.New(syncmode, chainDb, new(event.TypeMux), chain, nil, nil, nil)

// Create a source peer to satisfy downloader requests from
db, err := rawdb.NewLevelDBDatabase(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name), 256, "")
Expand Down
4 changes: 2 additions & 2 deletions cmd/XDC/consolecmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func TestConsoleWelcome(t *testing.T) {
XDC.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
XDC.SetTemplateFunc("gover", runtime.Version)
XDC.SetTemplateFunc("XDCver", func() string { return params.Version })
XDC.SetTemplateFunc("niltime", func() string { return time.Unix(1544771829, 0).Format(time.RFC1123) })
XDC.SetTemplateFunc("niltime", func() string { return time.Unix(1559211559, 0).Format(time.RFC1123) })
XDC.SetTemplateFunc("apis", func() string { return ipcAPIs })

// Verify the actual welcome message to the required template
Expand Down Expand Up @@ -137,7 +137,7 @@ func testAttachWelcome(t *testing.T, XDC *testXDC, endpoint, apis string) {
attach.SetTemplateFunc("gover", runtime.Version)
attach.SetTemplateFunc("XDCver", func() string { return params.Version })
attach.SetTemplateFunc("etherbase", func() string { return XDC.Etherbase })
attach.SetTemplateFunc("niltime", func() string { return time.Unix(1544771829, 0).Format(time.RFC1123) })
attach.SetTemplateFunc("niltime", func() string { return time.Unix(1559211559, 0).Format(time.RFC1123) })
attach.SetTemplateFunc("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") })
attach.SetTemplateFunc("datadir", func() string { return XDC.Datadir })
attach.SetTemplateFunc("apis", func() string { return apis })
Expand Down
7 changes: 7 additions & 0 deletions cmd/XDC/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ var (
utils.RPCVirtualHostsFlag,
utils.EthStatsURLFlag,
utils.MetricsEnabledFlag,
utils.MetricsHTTPFlag,
utils.MetricsPortFlag,
//utils.FakePoWFlag,
//utils.NoCompactionFlag,
//utils.GpoBlocksFlag,
Expand Down Expand Up @@ -290,6 +292,11 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) {
if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
utils.Fatalf("Light clients do not support staking")
}
// Start metrics export if enabled
utils.SetupMetrics(ctx)
// Start system runtime metrics collection
go metrics.CollectProcessMetrics(3 * time.Second)

var ethereum *eth.Ethereum
if err := stack.Service(&ethereum); err != nil {
utils.Fatalf("Ethereum service not running: %v", err)
Expand Down
27 changes: 27 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/metrics"
"github.com/XinFinOrg/XDPoSChain/metrics/exp"
"github.com/XinFinOrg/XDPoSChain/node"
"github.com/XinFinOrg/XDPoSChain/p2p"
"github.com/XinFinOrg/XDPoSChain/p2p/discover"
Expand Down Expand Up @@ -355,6 +356,20 @@ var (
Name: "ethstats",
Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
}
// MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint.
// Since the pprof service enables sensitive/vulnerable behavior, this allows a user
// to enable a public-OK metrics endpoint without having to worry about ALSO exposing
// other profiling behavior or information.
MetricsHTTPFlag = cli.StringFlag{
Name: "metrics.addr",
Usage: "Enable stand-alone metrics HTTP server listening interface",
Value: metrics.DefaultConfig.HTTP,
}
MetricsPortFlag = cli.IntFlag{
Name: "metrics.port",
Usage: "Metrics HTTP server listening port",
Value: metrics.DefaultConfig.Port,
}
MetricsEnabledFlag = cli.BoolFlag{
Name: metrics.MetricsEnabledFlag,
Usage: "Enable metrics collection and reporting",
Expand Down Expand Up @@ -1330,3 +1345,15 @@ func WalkMatch(root, pattern string) ([]string, error) {
}
return matches, nil
}

func SetupMetrics(ctx *cli.Context) {
if metrics.Enabled {
log.Info("Enabling metrics collection")

if ctx.GlobalIsSet(MetricsHTTPFlag.Name) {
address := fmt.Sprintf("%s:%d", ctx.GlobalString(MetricsHTTPFlag.Name), ctx.GlobalInt(MetricsPortFlag.Name))
log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address)
exp.Setup(address)
}
}
}
1 change: 1 addition & 0 deletions common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
MaxMasternodes = 18
MaxMasternodesV2 = 108
LimitPenaltyEpoch = 4
LimitPenaltyEpochV2 = 0
BlocksPerYearTest = uint64(200000)
BlocksPerYear = uint64(15768000)
LimitThresholdNonceInQueue = 10
Expand Down
87 changes: 87 additions & 0 deletions common/countdown/countdown.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// A countdown timer that will mostly be used by XDPoS v2 consensus engine
package countdown

import (
"sync"
"time"

"github.com/XinFinOrg/XDPoSChain/log"
)

type CountdownTimer struct {
lock sync.RWMutex // Protects the Initilised field
resetc chan int
quitc chan chan struct{}
initilised bool
timeoutDuration time.Duration
// Triggered when the countdown timer timeout for the `timeoutDuration` period, it will pass current timestamp to the callback function
OnTimeoutFn func(time time.Time, i interface{}) error
}

func NewCountDown(duration time.Duration) *CountdownTimer {
return &CountdownTimer{
resetc: make(chan int),
quitc: make(chan chan struct{}),
initilised: false,
timeoutDuration: duration,
}
}

// Completely stop the countdown timer from running.
func (t *CountdownTimer) StopTimer() {
q := make(chan struct{})
t.quitc <- q
<-q
}

// Reset will start the countdown timer if it's already stopped, or simply reset the countdown time back to the defual `duration`
func (t *CountdownTimer) Reset(i interface{}) {
if !t.isInitilised() {
t.setInitilised(true)
go t.startTimer(i)
} else {
t.resetc <- 0
}
}

// A long running process that
func (t *CountdownTimer) startTimer(i interface{}) {
// Make sure we mark Initilised to false when we quit the countdown
defer t.setInitilised(false)
timer := time.NewTimer(t.timeoutDuration)
// We start with a inf loop
for {
select {
case q := <-t.quitc:
log.Debug("Quit countdown timer")
close(q)
return
case <-timer.C:
log.Debug("Countdown time reached!")
go func() {
err := t.OnTimeoutFn(time.Now(), i)
if err != nil {
log.Error("OnTimeoutFn error", "error", err)
}
log.Debug("OnTimeoutFn processed")
}()
timer.Reset(t.timeoutDuration)
case <-t.resetc:
log.Debug("Reset countdown timer")
timer.Reset(t.timeoutDuration)
}
}
}

// Set the desired value to Initilised with lock to avoid race condition
func (t *CountdownTimer) setInitilised(value bool) {
t.lock.Lock()
defer t.lock.Unlock()
t.initilised = value
}

func (t *CountdownTimer) isInitilised() bool {
t.lock.Lock()
defer t.lock.Unlock()
return t.initilised
}
Loading

0 comments on commit 22479f1

Please sign in to comment.