mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 13:44:31 +00:00
commit
931fa283fb
24 changed files with 499 additions and 136 deletions
6
.github/CONTRIBUTING.md
vendored
6
.github/CONTRIBUTING.md
vendored
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
Before you do a feature request please check and make sure that it isn't possible
|
||||
through some other means. The JavaScript enabled console is a powerful feature
|
||||
in the right hands.
|
||||
in the right hands. Please check our [Wiki page](https://github.com/ethereum/go-ethereum/wiki) for more info
|
||||
and help.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
@ -10,3 +11,6 @@ If you'd like to contribute to go-ethereum please fork, fix, commit and
|
|||
send a pull request. Commits which do not comply with the coding standards
|
||||
are ignored (use gofmt!).
|
||||
|
||||
See [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide)
|
||||
for more details on configuring your environment, testing, and
|
||||
dependency management.
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ FROM golang:1.10-alpine as builder
|
|||
|
||||
RUN apk add --no-cache make gcc musl-dev linux-headers
|
||||
|
||||
ADD . /XDChain
|
||||
ADD . /XDCchain
|
||||
|
||||
RUN cd /XDChain \
|
||||
&& make XDC\
|
||||
RUN cd /XDCchain \
|
||||
&& make XDC \
|
||||
&& chmod +x /XDCchain/build/bin/XDC
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
LABEL maintainer="anil@xinfin.org"
|
||||
|
||||
WORKDIR /XDChain
|
||||
WORKDIR /XDCchain
|
||||
|
||||
COPY --from=builder /XDCchain/build/bin/XDC /usr/local/bin/XDC
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ ENV ANNOUNCE_TXS ''
|
|||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
COPY docker/XDChain ./
|
||||
COPY docker/XDCchain ./
|
||||
COPY genesis/ ./
|
||||
|
||||
EXPOSE 8545 8546 30303 30303/udp
|
||||
|
|
|
|||
5
Makefile
5
Makefile
|
|
@ -15,6 +15,11 @@ XDC:
|
|||
@echo "Done building."
|
||||
@echo "Run \"$(GOBIN)/XDC\" to launch XDC."
|
||||
|
||||
gc:
|
||||
build/env.sh go run build/ci.go install ./cmd/gc
|
||||
@echo "Done building."
|
||||
@echo "Run \"$(GOBIN)/gc\" to launch gc."
|
||||
|
||||
bootnode:
|
||||
build/env.sh go run build/ci.go install ./cmd/bootnode
|
||||
@echo "Done building."
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
|
|
@ -14,17 +21,18 @@ import (
|
|||
"github.com/hashicorp/golang-lru"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
dir = flag.String("dir", "", "dir to mainet chain data")
|
||||
cacheSize = flag.Int("size", 1000000, "dir to mainet chain data")
|
||||
dir = flag.String("dir", "", "directory to XDCChain chaindata")
|
||||
cacheSize = flag.Int("size", 1000000, "LRU cache size")
|
||||
sercureKey = []byte("secure-key-")
|
||||
nWorker = runtime.NumCPU() / 2
|
||||
cleanAddress = []common.Address{common.HexToAddress(common.BlockSigners)}
|
||||
cache *lru.Cache
|
||||
finish = int32(0)
|
||||
running = true
|
||||
stateRoots = make(chan TrieRoot)
|
||||
)
|
||||
|
||||
type TrieRoot struct {
|
||||
|
|
@ -42,14 +50,6 @@ type ResultProcessNode struct {
|
|||
keys [17]*[]byte
|
||||
}
|
||||
|
||||
var sercureKey = []byte("secure-key-")
|
||||
var nWorker = runtime.NumCPU() / 2
|
||||
var cleanAddress = []common.Address{common.HexToAddress(common.BlockSigners)}
|
||||
var cache *lru.Cache
|
||||
var finish = int32(0)
|
||||
var running = true
|
||||
var stateRoots = make(chan TrieRoot)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
lddb, _ := ethdb.NewLDBDatabase(*dir, eth.DefaultConfig.DatabaseCache, utils.MakeDatabaseHandles())
|
||||
|
|
@ -122,8 +122,8 @@ func (w *wizard) makeGenesis() {
|
|||
genesis.Config.XDPoS.Period = uint64(w.readDefaultInt(2))
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("How many XDC should be rewarded to masternode? (default = 100)")
|
||||
genesis.Config.XDPoS.Reward = uint64(w.readDefaultInt(100))
|
||||
fmt.Println("How many XDC should be rewarded to masternode? (default = 350)")
|
||||
genesis.Config.XDPoS.Reward = uint64(w.readDefaultInt(350))
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("Who own the first masternodes? (mandatory)")
|
||||
|
|
@ -231,8 +231,8 @@ func (w *wizard) makeGenesis() {
|
|||
code, _ = contractBackend.CodeAt(ctx, multiSignWalletAddr, nil)
|
||||
storage = make(map[common.Hash]common.Hash)
|
||||
contractBackend.ForEachStorageAt(ctx, multiSignWalletAddr, nil, f)
|
||||
fBalance := big.NewInt(0) // 16m
|
||||
fBalance.Add(fBalance, big.NewInt(16*1000*1000))
|
||||
fBalance := big.NewInt(0) // 3 billion
|
||||
fBalance.Add(fBalance, big.NewInt(3*1000*1000*1000))
|
||||
fBalance.Mul(fBalance, big.NewInt(1000000000000000000))
|
||||
genesis.Alloc[common.HexToAddress(common.FoudationAddr)] = core.GenesisAccount{
|
||||
Balance: fBalance,
|
||||
|
|
@ -298,24 +298,24 @@ func (w *wizard) makeGenesis() {
|
|||
storage = make(map[common.Hash]common.Hash)
|
||||
contractBackend.ForEachStorageAt(ctx, multiSignWalletTeamAddr, nil, f)
|
||||
// Team balance.
|
||||
balance := big.NewInt(0) // 12m
|
||||
balance.Add(balance, big.NewInt(12*1000*1000))
|
||||
balance.Mul(balance, big.NewInt(1000000000000000000))
|
||||
subBalance := big.NewInt(0) // i * 50k
|
||||
subBalance.Add(subBalance, big.NewInt(int64(len(signers))*50*1000))
|
||||
subBalance.Mul(subBalance, big.NewInt(1000000000000000000))
|
||||
balance.Sub(balance, subBalance) // 12m - i * 50k
|
||||
genesis.Alloc[common.HexToAddress(common.TeamAddr)] = core.GenesisAccount{
|
||||
balance := big.NewInt(0) // 20 billion
|
||||
balance.Add(balance, big.NewInt(20*1000*1000*1000))
|
||||
balance.Mul(balance, big.NewInt(1000000000000000000))
|
||||
subBalance := big.NewInt(0) // i * 50k
|
||||
subBalance.Add(subBalance, big.NewInt(int64(len(signers))*50*1000))
|
||||
subBalance.Mul(subBalance, big.NewInt(1000000000000000000))
|
||||
balance.Sub(balance, subBalance) // 12m - i * 50k
|
||||
genesis.Alloc[common.HexToAddress(common.TeamAddr)] = core.GenesisAccount{
|
||||
Balance: balance,
|
||||
Code: code,
|
||||
Storage: storage,
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("What is swap wallet address for fund 55m XDC?")
|
||||
fmt.Println("What is swap wallet address for fund 14.5Billion XDC?")
|
||||
swapAddr := *w.readAddress()
|
||||
baseBalance := big.NewInt(0) // 55m
|
||||
baseBalance.Add(baseBalance, big.NewInt(55*1000*1000))
|
||||
baseBalance := big.NewInt(0) // 14.5Billion
|
||||
baseBalance.Add(baseBalance, big.NewInt(145*1000*1000*100))
|
||||
baseBalance.Mul(baseBalance, big.NewInt(1000000000000000000))
|
||||
genesis.Alloc[swapAddr] = core.GenesisAccount{
|
||||
Balance: baseBalance,
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ const (
|
|||
MinimunMinerBlockPerEpoch = 1
|
||||
)
|
||||
|
||||
var TIP2019Block = big.NewInt(1050000)
|
||||
var TIP2019Block = big.NewInt(1)
|
||||
var TIPSigning = big.NewInt(3000000)
|
||||
var TIPRandomize = big.NewInt(3464000)
|
||||
var IsTestnet bool = false
|
||||
var StoreRewardFolder string
|
||||
var RollbackHash Hash
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Package XDPoS implements the delegated-proof-of-stake consensus engine.
|
||||
// Package XDPoS implements the proof-of-stake-voting consensus engine.
|
||||
package XDPoS
|
||||
|
||||
import (
|
||||
|
|
@ -25,6 +25,8 @@ import (
|
|||
"math/big"
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -58,7 +60,7 @@ type Masternode struct {
|
|||
Stake *big.Int
|
||||
}
|
||||
|
||||
// XDPoS delegated-proof-of-stake protocol constants.
|
||||
// XDPoS proof-of-stake-voting protocol constants.
|
||||
var (
|
||||
epochLength = uint64(900) // Default number of blocks after which to checkpoint and reset the pending votes
|
||||
|
||||
|
|
@ -149,7 +151,7 @@ var (
|
|||
// backing account.
|
||||
//type SignerFn func(accounts.Account, []byte) ([]byte, error)
|
||||
|
||||
// sigHash returns the hash which is used as input for the delegated-proof-of-stake
|
||||
// sigHash returns the hash which is used as input for the proof-of-stake-voting
|
||||
// signing. It is the hash of the entire header apart from the 65 byte signature
|
||||
// contained at the end of the extra data.
|
||||
//
|
||||
|
|
@ -209,7 +211,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er
|
|||
return signer, nil
|
||||
}
|
||||
|
||||
// XDPoS is the delegated-proof-of-stake consensus engine proposed to support the
|
||||
// XDPoS is the proof-of-stake-voting consensus engine proposed to support the
|
||||
// Ethereum testnet following the Ropsten attacks.
|
||||
type XDPoS struct {
|
||||
config *params.XDPoSConfig // Consensus engine configuration parameters
|
||||
|
|
@ -225,15 +227,15 @@ type XDPoS struct {
|
|||
signFn clique.SignerFn // Signer function to authorize hashes with
|
||||
lock sync.RWMutex // Protects the signer fields
|
||||
|
||||
BlockSigners *lru.Cache
|
||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{})
|
||||
BlockSigners *lru.Cache
|
||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{})
|
||||
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
||||
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error)
|
||||
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
||||
HookVerifyMNs func(header *types.Header, signers []common.Address) error
|
||||
}
|
||||
|
||||
// New creates a XDPoS delegated-proof-of-stake consensus engine with the initial
|
||||
// New creates a XDPoS proof-of-stake-voting consensus engine with the initial
|
||||
// signers set to the ones provided by the user.
|
||||
func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
|
||||
// Set any missing consensus parameters to their defaults
|
||||
|
|
@ -424,9 +426,11 @@ func (c *XDPoS) verifyCascadingFields(chain consensus.ChainReader, header *types
|
|||
signers = RemovePenaltiesFromBlock(chain, signers, number-uint64(i)*c.config.Epoch)
|
||||
}
|
||||
}
|
||||
byteMasterNodes := common.ExtractAddressToBytes(signers)
|
||||
extraSuffix := len(header.Extra) - extraSeal
|
||||
if !bytes.Equal(header.Extra[extraVanity:extraSuffix], byteMasterNodes) {
|
||||
masternodesFromCheckpointHeader := common.ExtractAddressFromBytes(header.Extra[extraVanity:extraSuffix])
|
||||
validSigners := compareSignersLists(masternodesFromCheckpointHeader, signers)
|
||||
if !validSigners {
|
||||
log.Error("Masternodes lists are different in checkpoint header and snapshot", "number", number, "masternodes_from_checkpoint_header", masternodesFromCheckpointHeader, "masternodes_in_snapshot", signers, "penList", penPenalties)
|
||||
return errInvalidCheckpointSigners
|
||||
}
|
||||
if c.HookVerifyMNs != nil {
|
||||
|
|
@ -440,6 +444,21 @@ func (c *XDPoS) verifyCascadingFields(chain consensus.ChainReader, header *types
|
|||
return c.verifySeal(chain, header, parents, fullVerify)
|
||||
}
|
||||
|
||||
// compare 2 signers lists
|
||||
// return true if they are same elements, otherwise return false
|
||||
func compareSignersLists(list1 []common.Address, list2 []common.Address) bool {
|
||||
if len(list1) == 0 && len(list2) == 0 {
|
||||
return true
|
||||
}
|
||||
sort.Slice(list1, func(i, j int) bool {
|
||||
return list1[i].String() <= list1[j].String()
|
||||
})
|
||||
sort.Slice(list2, func(i, j int) bool {
|
||||
return list2[i].String() <= list2[j].String()
|
||||
})
|
||||
return reflect.DeepEqual(list1, list2)
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*Snapshot, error) {
|
||||
number := header.Number.Uint64()
|
||||
log.Trace("take snapshot", "number", number, "hash", header.Hash())
|
||||
|
|
@ -739,7 +758,7 @@ func (c *XDPoS) GetValidator(creator common.Address, chain consensus.ChainReader
|
|||
return common.Address{}, fmt.Errorf("couldn't find checkpoint header")
|
||||
}
|
||||
}
|
||||
m, err := GetM1M2FromCheckpointHeader(cpHeader)
|
||||
m, err := GetM1M2FromCheckpointHeader(cpHeader, header, chain.Config())
|
||||
if err != nil {
|
||||
return common.Address{}, err
|
||||
}
|
||||
|
|
@ -977,7 +996,13 @@ func (c *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, stop <-cha
|
|||
return nil, err
|
||||
}
|
||||
copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
|
||||
|
||||
m2, err := c.GetValidator(signer, chain, header)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't get block validator: %v", err)
|
||||
}
|
||||
if m2 == signer {
|
||||
header.Validator = sighash
|
||||
}
|
||||
return block.WithSeal(header), nil
|
||||
}
|
||||
|
||||
|
|
@ -1119,26 +1144,41 @@ func GetMasternodesFromCheckpointHeader(checkpointHeader *types.Header) []common
|
|||
}
|
||||
|
||||
// Get m2 list from checkpoint block.
|
||||
func GetM1M2FromCheckpointHeader(checkpointHeader *types.Header) (map[common.Address]common.Address, error) {
|
||||
func GetM1M2FromCheckpointHeader(checkpointHeader *types.Header, currentHeader *types.Header, config *params.ChainConfig) (map[common.Address]common.Address, error) {
|
||||
if checkpointHeader.Number.Uint64()%common.EpocBlockRandomize != 0 {
|
||||
return nil, errors.New("This block is not checkpoint block epoc.")
|
||||
}
|
||||
m1m2 := map[common.Address]common.Address{}
|
||||
// Get signers from this block.
|
||||
masternodes := GetMasternodesFromCheckpointHeader(checkpointHeader)
|
||||
validators := ExtractValidatorsFromBytes(checkpointHeader.Validators)
|
||||
|
||||
if len(validators) < len(masternodes) {
|
||||
return nil, errors.New("len(m2) is less than len(m1)")
|
||||
}
|
||||
if len(masternodes) > 0 {
|
||||
for i, m1 := range masternodes {
|
||||
m1m2[m1] = masternodes[validators[i]%int64(len(masternodes))]
|
||||
}
|
||||
m1m2, _, err := getM1M2(masternodes, validators, currentHeader, config)
|
||||
if err != nil {
|
||||
return map[common.Address]common.Address{}, err
|
||||
}
|
||||
return m1m2, nil
|
||||
}
|
||||
|
||||
func getM1M2(masternodes []common.Address, validators []int64, currentHeader *types.Header, config *params.ChainConfig) (map[common.Address]common.Address, uint64, error) {
|
||||
m1m2 := map[common.Address]common.Address{}
|
||||
maxMNs := len(masternodes)
|
||||
moveM2 := uint64(0)
|
||||
if len(validators) < maxMNs {
|
||||
return nil, moveM2, errors.New("len(m2) is less than len(m1)")
|
||||
}
|
||||
if maxMNs > 0 {
|
||||
isForked := config.IsTIPRandomize(currentHeader.Number)
|
||||
if isForked {
|
||||
moveM2 = ((currentHeader.Number.Uint64() % config.XDPoS.Epoch) / uint64(maxMNs)) % uint64(maxMNs)
|
||||
}
|
||||
for i, m1 := range masternodes {
|
||||
m2Index := uint64(validators[i] % int64(maxMNs))
|
||||
m2Index = (m2Index + moveM2) % uint64(maxMNs)
|
||||
m1m2[m1] = masternodes[m2Index]
|
||||
}
|
||||
}
|
||||
return m1m2, moveM2, nil
|
||||
}
|
||||
|
||||
// Extract validators from byte array.
|
||||
func ExtractValidatorsFromBytes(byteValidators []byte) []int64 {
|
||||
lenValidator := len(byteValidators) / M2ByteLength
|
||||
|
|
|
|||
84
consensus/XDPoS/XDPoS_test.go
Normal file
84
consensus/XDPoS/XDPoS_test.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package XDPoS
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func TestGetM1M2FromCheckpointHeader(t *testing.T) {
|
||||
masternodes := []common.Address{
|
||||
common.StringToAddress("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
|
||||
common.StringToAddress("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
|
||||
common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc"),
|
||||
}
|
||||
validators := []int64{
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
}
|
||||
epoch := uint64(900)
|
||||
config := ¶ms.ChainConfig{
|
||||
XDPoS: ¶ms.XDPoSConfig{
|
||||
Epoch: uint64(epoch),
|
||||
},
|
||||
}
|
||||
testMoveM2 := []uint64{0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, 2, 2, 2}
|
||||
//try from block 3410001 to 3410018
|
||||
for i := uint64(3464001); i <= 3464018; i++ {
|
||||
currentNumber := int64(i)
|
||||
currentHeader := &types.Header{
|
||||
Number: big.NewInt(currentNumber),
|
||||
}
|
||||
m1m2, moveM2, err := getM1M2(masternodes, validators, currentHeader, config)
|
||||
if err != nil {
|
||||
t.Error("can't get m1m2", "err", err)
|
||||
}
|
||||
fmt.Printf("block: %v, moveM2: %v\n", currentHeader.Number.Int64(), moveM2)
|
||||
for _, k := range masternodes {
|
||||
fmt.Printf("m1: %v - m2: %v\n", k.Str(), m1m2[k].Str())
|
||||
}
|
||||
if moveM2 != testMoveM2[i-3464001] {
|
||||
t.Error("wrong moveM2", "currentNumber", currentNumber, "want", testMoveM2[i-3464001], "have", moveM2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareSignersLists(t *testing.T) {
|
||||
list1 := []common.Address{
|
||||
common.StringToAddress("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
|
||||
common.StringToAddress("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
|
||||
common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc"),
|
||||
common.StringToAddress("dddddddddddddddddddddddddddddddddddddddd"),
|
||||
}
|
||||
list2 := []common.Address{
|
||||
common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc"),
|
||||
common.StringToAddress("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
|
||||
common.StringToAddress("dddddddddddddddddddddddddddddddddddddddd"),
|
||||
common.StringToAddress("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
|
||||
}
|
||||
list3 := []common.Address{
|
||||
common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc"),
|
||||
common.StringToAddress("dddddddddddddddddddddddddddddddddddddddd"),
|
||||
common.StringToAddress("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
|
||||
}
|
||||
if !compareSignersLists(list1, list2) {
|
||||
t.Error("list1 should be equal to list2", "list1", list1, "list2", list2)
|
||||
}
|
||||
if compareSignersLists(list1, list3) {
|
||||
t.Error("list1 and list3 should not be same", "list1", list1, "list3", list3)
|
||||
}
|
||||
if !compareSignersLists([]common.Address{}, []common.Address{}) {
|
||||
t.Error("Failed with empty list")
|
||||
}
|
||||
if !compareSignersLists([]common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}, []common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}) {
|
||||
t.Error("Failed with list has only one signer")
|
||||
}
|
||||
if compareSignersLists([]common.Address{common.StringToAddress("aaaaaaaaaaaaaaaa")}, []common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}) {
|
||||
t.Error("Failed with list has only one signer")
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ package contracts
|
|||
// "randomSecret": 0,
|
||||
// "randomOpening": 1,
|
||||
// }
|
||||
// datadir = "/mnt/sgp1_tuna_chaindata3/data/XDCchaindata"
|
||||
// datadir = "/mnt/sgp1_tuna_chaindata3/data/XDC/chaindata"
|
||||
// candidate = "0xd6fa3e7a89bf8c84f0ccd204a15c0d259daf2091"
|
||||
//)
|
||||
//
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ func GetRewardBalancesRate(foundationWalletAddr common.Address, state *state.Sta
|
|||
log.Error("Fail to parse json holders", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Info("Holders reward", "holders", string(jsonHolders), "master node", masterAddr.String())
|
||||
log.Trace("Holders reward", "holders", string(jsonHolders), "masternode", masterAddr.String())
|
||||
|
||||
return balances, nil
|
||||
}
|
||||
|
|
@ -503,7 +503,8 @@ func Encrypt(key []byte, text string) string {
|
|||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Error("Fail to encrypt", "err", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// The IV needs to be unique, but not secure. Therefore it's common to
|
||||
|
|
@ -511,7 +512,8 @@ func Encrypt(key []byte, text string) string {
|
|||
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(cryptoRand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
log.Error("Fail to encrypt iv", "err", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
|
|
@ -527,13 +529,15 @@ func Decrypt(key []byte, cryptoText string) string {
|
|||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Error("Fail to decrypt", "err", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// The IV needs to be unique, but not secure. Therefore it's common to
|
||||
// include it at the beginning of the ciphertext.
|
||||
if len(ciphertext) < aes.BlockSize {
|
||||
panic("ciphertext too short")
|
||||
log.Error("ciphertext too short")
|
||||
return ""
|
||||
}
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
ciphertext = ciphertext[aes.BlockSize:]
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ func TestRewardBalance(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common.Address, totalReward *big.Int, validator *contractValidator.XDCValidator) (map[common.Address]*big.Int, error) {
|
||||
func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common.Address, totalReward *big.Int, validator *contractValidator.XDCalidator) (map[common.Address]*big.Int, error) {
|
||||
owner := GetCandidatesOwnerBySigner(validator, masterAddr)
|
||||
balances := make(map[common.Address]*big.Int)
|
||||
rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent))
|
||||
|
|
|
|||
191
docker/XDCchain/entrypoint.sh
Normal file
191
docker/XDCchain/entrypoint.sh
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
#!/bin/sh
|
||||
|
||||
# vars from docker env
|
||||
# - IDENTITY (default to empty)
|
||||
# - PASSWORD (default to empty)
|
||||
# - PRIVATE_KEY (default to empty)
|
||||
# - BOOTNODES (default to empty)
|
||||
# - EXTIP (default to empty)
|
||||
# - VERBOSITY (default to 3)
|
||||
# - MAXPEERS (default to 25)
|
||||
# - SYNC_MODE (default to 'full')
|
||||
# - NETWORK_ID (default to '89')
|
||||
# - WS_SECRET (default to empty)
|
||||
# - NETSTATS_HOST (default to 'netstats-server:3000')
|
||||
# - NETSTATS_PORT (default to 'netstats-server:3000')
|
||||
|
||||
# constants
|
||||
DATA_DIR="data"
|
||||
KEYSTORE_DIR="keystore"
|
||||
|
||||
# variables
|
||||
genesisPath=""
|
||||
params=""
|
||||
accountsCount=$(
|
||||
XDC account list --datadir $DATA_DIR --keystore $KEYSTORE_DIR \
|
||||
2> /dev/null \
|
||||
| wc -l
|
||||
)
|
||||
|
||||
# file to env
|
||||
for env in IDENTITY PASSWORD PRIVATE_KEY BOOTNODES WS_SECRET NETSTATS_HOST \
|
||||
NETSTATS_PORT EXTIP SYNC_MODE NETWORK_ID ANNOUNCE_TXS STORE_REWARD DEBUG_MODE MAXPEERS; do
|
||||
file=$(eval echo "\$${env}_FILE")
|
||||
if [[ -f $file ]] && [[ ! -z $file ]]; then
|
||||
echo "Replacing $env by $file"
|
||||
export $env=$(cat $file)
|
||||
elif [[ "$env" == "BOOTNODES" ]] && [[ ! -z $file ]]; then
|
||||
echo "Bootnodes file is not available. Waiting for it to be provisioned..."
|
||||
while true ; do
|
||||
if [[ -f $file ]] && [[ $(grep -e enode $file) ]]; then
|
||||
echo "Fount bootnode file."
|
||||
break
|
||||
fi
|
||||
echo "Still no bootnodes file, sleeping..."
|
||||
sleep 5
|
||||
done
|
||||
export $env=$(cat $file)
|
||||
fi
|
||||
done
|
||||
|
||||
# networkid
|
||||
if [[ ! -z $NETWORK_ID ]]; then
|
||||
case $NETWORK_ID in
|
||||
88 )
|
||||
genesisPath="mainnet.json"
|
||||
;;
|
||||
89 )
|
||||
genesisPath="testnet.json"
|
||||
params="$params --XDC-testnet --gcmode archive --rpcapi db,eth,net,web3,personal,debug"
|
||||
;;
|
||||
90 )
|
||||
genesisPath="devnet.json"
|
||||
;;
|
||||
* )
|
||||
echo "network id not supported"
|
||||
;;
|
||||
esac
|
||||
params="$params --networkid $NETWORK_ID"
|
||||
fi
|
||||
|
||||
# data dir
|
||||
if [[ ! -d $DATA_DIR/XDC ]]; then
|
||||
echo "No blockchain data, creating genesis block."
|
||||
XDC init $genesisPath --datadir $DATA_DIR 2> /dev/null
|
||||
fi
|
||||
|
||||
# identity
|
||||
if [[ -z $IDENTITY ]]; then
|
||||
IDENTITY="unnamed_$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c6)"
|
||||
fi
|
||||
|
||||
# password file
|
||||
if [[ ! -f ./password ]]; then
|
||||
if [[ ! -z $PASSWORD ]]; then
|
||||
echo "Password env is set. Writing into file."
|
||||
echo "$PASSWORD" > ./password
|
||||
else
|
||||
echo "No password set (or empty), generating a new one"
|
||||
$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32} > password)
|
||||
fi
|
||||
fi
|
||||
|
||||
# private key
|
||||
if [[ $accountsCount -le 0 ]]; then
|
||||
echo "No accounts found"
|
||||
if [[ ! -z $PRIVATE_KEY ]]; then
|
||||
echo "Creating account from private key"
|
||||
echo "$PRIVATE_KEY" > ./private_key
|
||||
XDC account import ./private_key \
|
||||
--datadir $DATA_DIR \
|
||||
--keystore $KEYSTORE_DIR \
|
||||
--password ./password
|
||||
rm ./private_key
|
||||
else
|
||||
echo "Creating new account"
|
||||
XDC account new \
|
||||
--datadir $DATA_DIR \
|
||||
--keystore $KEYSTORE_DIR \
|
||||
--password ./password
|
||||
fi
|
||||
fi
|
||||
account=$(
|
||||
XDC account list --datadir $DATA_DIR --keystore $KEYSTORE_DIR \
|
||||
2> /dev/null \
|
||||
| head -n 1 \
|
||||
| cut -d"{" -f 2 | cut -d"}" -f 1
|
||||
)
|
||||
echo "Using account $account"
|
||||
params="$params --unlock $account"
|
||||
|
||||
# bootnodes
|
||||
if [[ ! -z $BOOTNODES ]]; then
|
||||
params="$params --bootnodes $BOOTNODES"
|
||||
fi
|
||||
|
||||
# extip
|
||||
if [[ ! -z $EXTIP ]]; then
|
||||
params="$params --nat extip:${EXTIP}"
|
||||
fi
|
||||
|
||||
# syncmode
|
||||
if [[ ! -z $SYNC_MODE ]]; then
|
||||
params="$params --syncmode ${SYNC_MODE}"
|
||||
fi
|
||||
|
||||
# netstats
|
||||
if [[ ! -z $WS_SECRET ]]; then
|
||||
echo "Will report to netstats server ${NETSTATS_HOST}:${NETSTATS_PORT}"
|
||||
params="$params --ethstats ${IDENTITY}:${WS_SECRET}@${NETSTATS_HOST}:${NETSTATS_PORT}"
|
||||
else
|
||||
echo "WS_SECRET not set, will not report to netstats server."
|
||||
fi
|
||||
|
||||
# annonce txs
|
||||
if [[ ! -z $ANNOUNCE_TXS ]]; then
|
||||
params="$params --announce-txs"
|
||||
fi
|
||||
|
||||
# store reward
|
||||
if [[ ! -z $STORE_REWARD ]]; then
|
||||
params="$params --store-reward"
|
||||
fi
|
||||
|
||||
# debug mode
|
||||
if [[ ! -z $DEBUG_MODE ]]; then
|
||||
params="$params --gcmode archive --rpcapi db,eth,net,web3,personal,debug"
|
||||
fi
|
||||
|
||||
# maxpeers
|
||||
if [[ -z $MAXPEERS ]]; then
|
||||
MAXPEERS=25
|
||||
fi
|
||||
|
||||
# dump
|
||||
echo "dump: $IDENTITY $account $BOOTNODES"
|
||||
|
||||
set -x
|
||||
|
||||
exec XDC $params \
|
||||
--verbosity $VERBOSITY \
|
||||
--datadir $DATA_DIR \
|
||||
--keystore $KEYSTORE_DIR \
|
||||
--identity $IDENTITY \
|
||||
--maxpeers $MAXPEERS \
|
||||
--password ./password \
|
||||
--port 30303 \
|
||||
--txpool.globalqueue 5000 \
|
||||
--txpool.globalslots 5000 \
|
||||
--rpc \
|
||||
--rpccorsdomain "*" \
|
||||
--rpcaddr 0.0.0.0 \
|
||||
--rpcport 8545 \
|
||||
--rpcvhosts "*" \
|
||||
--ws \
|
||||
--wsaddr 0.0.0.0 \
|
||||
--wsport 8546 \
|
||||
--wsorigins "*" \
|
||||
--mine \
|
||||
--gasprice "250000000" \
|
||||
--targetgaslimit "84000000" \
|
||||
"$@"
|
||||
|
|
@ -322,7 +322,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
c.HookPenaltyTIPSigning = func(chain consensus.ChainReader, header *types.Header, candidates []common.Address) ([]common.Address, error) {
|
||||
prevEpoc := header.Number.Uint64() - chain.Config().XDPoS.Epoch
|
||||
combackEpoch := uint64(0)
|
||||
comebackLength := uint64((common.LimitPenaltyEpoch + 1) * chain.Config().XDPoS.Epoch)
|
||||
comebackLength := (common.LimitPenaltyEpoch + 1) * chain.Config().XDPoS.Epoch
|
||||
if header.Number.Uint64() > comebackLength {
|
||||
combackEpoch = header.Number.Uint64() - comebackLength
|
||||
}
|
||||
|
|
@ -367,7 +367,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
penalties = append(penalties, addr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// get list check penalties signing block & list master nodes wil comeback
|
||||
penComebacks := []common.Address{}
|
||||
if combackEpoch > 0 {
|
||||
|
|
@ -419,8 +419,10 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
|
||||
log.Debug("Time Calculated HookPenaltyTIPSigning ", "block", header.Number, "hash", header.Hash().Hex(), "pen comeback nodes", len(penComebacks), "not enough miner", len(penalties), "time", common.PrettyDuration(time.Since(start)))
|
||||
penalties = append(penalties, penComebacks...)
|
||||
if chain.Config().IsTIPRandomize(header.Number) {
|
||||
return penalties, nil
|
||||
}
|
||||
return penComebacks, nil
|
||||
|
||||
}
|
||||
return []common.Address{}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ var (
|
|||
errCancelContentProcessing = errors.New("content processing canceled (requested)")
|
||||
errNoSyncActive = errors.New("no sync active")
|
||||
errTooOld = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)")
|
||||
errEnoughBlock = errors.New("downloader download enough block")
|
||||
)
|
||||
|
||||
type Downloader struct {
|
||||
|
|
@ -421,7 +422,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
|
|||
}(time.Now())
|
||||
|
||||
// Look up the sync boundaries: the common ancestor and the target block
|
||||
latest, err := d.fetchHeight(p)
|
||||
latest, err := d.fetchHeight(p, hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -469,7 +470,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
|
|||
if d.mode == FastSync {
|
||||
fetchers = append(fetchers, func() error { return d.processFastSyncContent(latest) })
|
||||
} else if d.mode == FullSync {
|
||||
fetchers = append(fetchers, d.processFullSyncContent)
|
||||
fetchers = append(fetchers, func() error { return d.processFullSyncContent(height) })
|
||||
}
|
||||
return d.spawnSync(fetchers)
|
||||
}
|
||||
|
|
@ -500,6 +501,9 @@ func (d *Downloader) spawnSync(fetchers []func() error) error {
|
|||
d.queue.Close()
|
||||
d.Cancel()
|
||||
wg.Wait()
|
||||
if err == errEnoughBlock {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -537,12 +541,10 @@ func (d *Downloader) Terminate() {
|
|||
|
||||
// fetchHeight retrieves the head header of the remote peer to aid in estimating
|
||||
// the total time a pending synchronisation would take.
|
||||
func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) {
|
||||
p.log.Debug("Retrieving remote chain height")
|
||||
func (d *Downloader) fetchHeight(p *peerConnection, hash common.Hash) (*types.Header, error) {
|
||||
|
||||
// Request the advertised remote head block and wait for the response
|
||||
head, _ := p.peer.Head()
|
||||
go p.peer.RequestHeadersByHash(head, 1, 0, false)
|
||||
go p.peer.RequestHeadersByHash(hash, 1, 0, false)
|
||||
|
||||
ttl := d.requestTTL()
|
||||
timeout := time.After(ttl)
|
||||
|
|
@ -1317,7 +1319,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
|
|||
}
|
||||
|
||||
// processFullSyncContent takes fetch results from the queue and imports them into the chain.
|
||||
func (d *Downloader) processFullSyncContent() error {
|
||||
func (d *Downloader) processFullSyncContent(height uint64) error {
|
||||
for {
|
||||
results := d.queue.Results(true)
|
||||
if len(results) == 0 {
|
||||
|
|
@ -1358,6 +1360,11 @@ func (d *Downloader) processFullSyncContent() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
latest := results[len(results)-1]
|
||||
if latest.Header != nil && latest.Header.Number.Uint64() > height {
|
||||
log.Debug("Force stop because downloading enough block", "height", height, "latest", latest.Header.Number.Uint64())
|
||||
return errEnoughBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -542,9 +542,9 @@ func hasXDCPrefix(str string) bool {
|
|||
}
|
||||
|
||||
func decodeAddress(s string) (common.Address, error) {
|
||||
if hasXDCPrefix(s) {
|
||||
s = "0x" + s[3:]
|
||||
}
|
||||
if hasXDCPrefix(s) {
|
||||
s = "0x" + s[3:]
|
||||
}
|
||||
b, err := hexutil.Decode(s)
|
||||
if err == nil && len(b) != common.AddressLength {
|
||||
err = fmt.Errorf("hex has invalid length %d after decoding", len(b))
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
},
|
||||
"nonce": "0x0",
|
||||
"timestamp": "0x5c107ff8",
|
||||
"timestamp": "0x5c1358f5",
|
||||
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000001b82c4bf317fcafe3d77e8b444c82715d216afe845b7bd987fa22c9bac89b71f0ded03f6e150ba31ad670b2b166684657ffff95f4810380ae7381e9bce41231d5dd8cdd7499e418b648c00af75d184a2f9aba09a6fa4a46fb1a6a3919b027d9cac5aa6890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x47b760",
|
||||
"difficulty": "0x1",
|
||||
|
|
@ -119,4 +119,4 @@
|
|||
"number": "0x0",
|
||||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,4 +110,4 @@
|
|||
"number": "0x0",
|
||||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
|
@ -33,6 +35,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
"github.com/ethereum/go-ethereum/consensus/XDPoS"
|
||||
"github.com/ethereum/go-ethereum/contracts"
|
||||
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
|
@ -44,17 +47,14 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultGasPrice = 50 * params.Shannon
|
||||
defaultGasPrice = 50 * params.Shannon
|
||||
// statuses of candidates
|
||||
statusMasternode = "MASTERNODE"
|
||||
statusSlashed = "SLASHED"
|
||||
statusProposed = "PROPOSED"
|
||||
|
||||
statusMasternode = "MASTERNODE"
|
||||
statusSlashed = "SLASHED"
|
||||
statusProposed = "PROPOSED"
|
||||
)
|
||||
|
||||
// PublicEthereumAPI provides an API to access Ethereum related information.
|
||||
|
|
@ -699,14 +699,13 @@ func (s *PublicBlockChainAPI) GetMasternodes(ctx context.Context, b *types.Block
|
|||
return masternodes, nil
|
||||
}
|
||||
|
||||
|
||||
// GetCandidateStatus returns status of the given candidate at a specified epochNumber
|
||||
func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAddress common.Address, epochNumber rpc.EpochNumber) (string, error) {
|
||||
var (
|
||||
block *types.Block
|
||||
masternodes, penaltyList, candidates, proposedList []common.Address
|
||||
penalties []byte
|
||||
err error
|
||||
block *types.Block
|
||||
masternodes, penaltyList []common.Address
|
||||
penalties []byte
|
||||
err error
|
||||
)
|
||||
block = s.b.CurrentBlock()
|
||||
epoch := s.b.ChainConfig().XDPoS.Epoch
|
||||
|
|
@ -735,27 +734,6 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
|
|||
}
|
||||
}
|
||||
|
||||
// look up recent checkpoint headers to get penalty list
|
||||
for i := 0; i <= common.LimitPenaltyEpoch; i++ {
|
||||
if blockNum > uint64(i) * epoch {
|
||||
blockCheckpointNumber := rpc.BlockNumber(blockNum - (blockNum % epoch) - (uint64(i) * epoch))
|
||||
blockCheckpoint, err := s.b.BlockByNumber(ctx, blockCheckpointNumber)
|
||||
if err != nil {
|
||||
log.Error("Failed to get block by number", "num", blockCheckpointNumber, "err", err)
|
||||
continue
|
||||
}
|
||||
penalties = append(penalties, blockCheckpoint.Penalties()...)
|
||||
}
|
||||
}
|
||||
if len(penalties) > 0 {
|
||||
penaltyList = common.ExtractAddressFromBytes(penalties)
|
||||
for _, pen := range penaltyList {
|
||||
if coinbaseAddress == pen {
|
||||
return statusSlashed, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read smart contract to get candidate list
|
||||
client, err := s.b.GetIPCClient()
|
||||
if err != nil {
|
||||
|
|
@ -767,21 +745,64 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
|
|||
return "", err
|
||||
}
|
||||
opts := new(bind.CallOpts)
|
||||
candidates, err = validator.GetCandidates(opts)
|
||||
var (
|
||||
candidateAddresses []common.Address
|
||||
candidates []XDPoS.Masternode
|
||||
)
|
||||
|
||||
candidateAddresses, err = validator.GetCandidates(opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// exclude masternodes
|
||||
proposedList = common.RemoveItemFromArray(candidates, masternodes)
|
||||
// exclude penalties
|
||||
proposedList = common.RemoveItemFromArray(proposedList, penaltyList)
|
||||
|
||||
for _, proposed := range proposedList {
|
||||
if coinbaseAddress == proposed {
|
||||
return statusProposed, nil
|
||||
for _, address := range candidateAddresses {
|
||||
v, err := validator.GetCandidateCap(opts, address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if address.String() != "xdc0000000000000000000000000000000000000000" {
|
||||
candidates = append(candidates, XDPoS.Masternode{Address: address, Stake: v})
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
// sort candidates by stake descending
|
||||
sort.Slice(candidates, func(i, j int) bool {
|
||||
return candidates[i].Stake.Cmp(candidates[j].Stake) >= 0
|
||||
})
|
||||
isTopCandidate := false // is candidates in top 150
|
||||
status := ""
|
||||
for i := 0; i < len(candidates); i++ {
|
||||
if candidates[i].Address == coinbaseAddress {
|
||||
status = statusProposed
|
||||
if i < common.MaxMasternodes {
|
||||
isTopCandidate = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if isTopCandidate == false {
|
||||
return status, nil
|
||||
}
|
||||
// look up recent checkpoint headers to get penalty list
|
||||
for i := 0; i <= common.LimitPenaltyEpoch; i++ {
|
||||
if blockNum > uint64(i)*epoch {
|
||||
blockCheckpointNumber := rpc.BlockNumber(blockNum - (blockNum % epoch) - (uint64(i) * epoch))
|
||||
blockCheckpoint, err := s.b.BlockByNumber(ctx, blockCheckpointNumber)
|
||||
if err != nil {
|
||||
log.Error("Failed to get block by number", "num", blockCheckpointNumber, "err", err)
|
||||
continue
|
||||
}
|
||||
penalties = append(penalties, blockCheckpoint.Penalties()...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(penalties) > 0 {
|
||||
penaltyList = common.ExtractAddressFromBytes(penalties)
|
||||
for _, pen := range penaltyList {
|
||||
if coinbaseAddress == pen {
|
||||
return statusSlashed, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// CallArgs represents the arguments for a call.
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ const (
|
|||
// timeout waiting for M1
|
||||
waitPeriod = 10
|
||||
// timeout for checkpoint.
|
||||
waitPeriodCheckpoint = 120 // 2 mins
|
||||
waitPeriodCheckpoint = 20
|
||||
)
|
||||
|
||||
// Agent can register themself with the worker
|
||||
|
|
@ -330,7 +330,7 @@ func (self *worker) wait() {
|
|||
continue
|
||||
}
|
||||
block := result.Block
|
||||
if self.config.XDPoS != nil && block.NumberU64() >= self.config.XDPoS.Epoch {
|
||||
if self.config.XDPoS != nil && block.NumberU64() >= self.config.XDPoS.Epoch && len(block.Validator()) == 0 {
|
||||
self.mux.Post(core.NewMinedBlockEvent{Block: block})
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ var (
|
|||
//
|
||||
// This configuration is intentionally not using keyed fields to force anyone
|
||||
// adding flags to the config to also have to set these fields.
|
||||
AllXDPoSProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &XDPoSConfig{Period: 0, Epoch: 30000}}
|
||||
AllXDPoSProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &XDPoSConfig{Period: 0, Epoch: 30000}}
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||
|
|
@ -121,7 +121,7 @@ type ChainConfig struct {
|
|||
// Various consensus engines
|
||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
||||
XDPoS *XDPoSConfig `json:"XDPoS,omitempty"`
|
||||
XDPoS *XDPoSConfig `json:"XDPoS,omitempty"`
|
||||
}
|
||||
|
||||
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
||||
|
|
@ -221,6 +221,10 @@ func (c *ChainConfig) IsTIPSigning(num *big.Int) bool {
|
|||
return isForked(common.TIPSigning, num)
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsTIPRandomize(num *big.Int) bool {
|
||||
return isForked(common.TIPRandomize, num)
|
||||
}
|
||||
|
||||
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
|
||||
//
|
||||
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
VersionMajor = 0 // Major version component of the current release
|
||||
VersionMinor = 5 // Minor version component of the current release
|
||||
VersionPatch = 0 // Patch version component of the current release
|
||||
VersionMajor = 0 // Major version component of the current release
|
||||
VersionMinor = 5 // Minor version component of the current release
|
||||
VersionPatch = 0 // Patch version component of the current release
|
||||
VersionMeta = "stable" // Version metadata to append to the version string
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -190,14 +190,14 @@ func (s *Server) serveRequest(codec ServerCodec, singleShot bool, options CodecO
|
|||
if singleShot {
|
||||
if batch {
|
||||
for _, req := range reqs {
|
||||
if req.callb != nil && req.callb.method.Name == "EnabledRPCSendTransaction" {
|
||||
if req.callb != nil && req.callb.method.Name == "SendTransaction" {
|
||||
codec.Write(codec.CreateErrorResponse(&req.id, &invalidRequestError{message: "Only support send transaction with ipc"}))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
s.execBatch(ctx, codec, reqs)
|
||||
} else {
|
||||
if reqs[0].callb != nil && reqs[0].callb.method.Name == "EnabledRPCSendTransaction" {
|
||||
if reqs[0].callb != nil && reqs[0].callb.method.Name == "SendTransaction" {
|
||||
codec.Write(codec.CreateErrorResponse(&reqs[0].id, &invalidRequestError{message: "Only support send transaction with ipc"}))
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ const (
|
|||
PendingBlockNumber = BlockNumber(-2)
|
||||
LatestBlockNumber = BlockNumber(-1)
|
||||
EarliestBlockNumber = BlockNumber(0)
|
||||
LatestEpochNumber = EpochNumber(-1)
|
||||
LatestEpochNumber = EpochNumber(-1)
|
||||
)
|
||||
|
||||
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
|
||||
|
|
|
|||
2
vendor/github.com/btcsuite/btcd/btcec/secp256k1.go
generated
vendored
2
vendor/github.com/btcsuite/btcd/btcec/secp256k1.go
generated
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue