Merge pull request #83 from XinFinOrg/develop

Fix Bad_Block issue
This commit is contained in:
Anil Chinchawale 2019-04-25 17:45:26 +05:30 committed by GitHub
commit 931fa283fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 499 additions and 136 deletions

View file

@ -2,7 +2,8 @@
Before you do a feature request please check and make sure that it isn't possible 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 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 ## 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 send a pull request. Commits which do not comply with the coding standards
are ignored (use gofmt!). 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.

View file

@ -2,17 +2,17 @@ FROM golang:1.10-alpine as builder
RUN apk add --no-cache make gcc musl-dev linux-headers RUN apk add --no-cache make gcc musl-dev linux-headers
ADD . /XDChain ADD . /XDCchain
RUN cd /XDChain \ RUN cd /XDCchain \
&& make XDC\ && make XDC \
&& chmod +x /XDCchain/build/bin/XDC && chmod +x /XDCchain/build/bin/XDC
FROM alpine:latest FROM alpine:latest
LABEL maintainer="anil@xinfin.org" LABEL maintainer="anil@xinfin.org"
WORKDIR /XDChain WORKDIR /XDCchain
COPY --from=builder /XDCchain/build/bin/XDC /usr/local/bin/XDC 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 RUN apk add --no-cache ca-certificates
COPY docker/XDChain ./ COPY docker/XDCchain ./
COPY genesis/ ./ COPY genesis/ ./
EXPOSE 8545 8546 30303 30303/udp EXPOSE 8545 8546 30303 30303/udp

View file

@ -15,6 +15,11 @@ XDC:
@echo "Done building." @echo "Done building."
@echo "Run \"$(GOBIN)/XDC\" to launch XDC." @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: bootnode:
build/env.sh go run build/ci.go install ./cmd/bootnode build/env.sh go run build/ci.go install ./cmd/bootnode
@echo "Done building." @echo "Done building."

View file

@ -3,6 +3,13 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"os"
"os/signal"
"runtime"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
@ -14,17 +21,18 @@ import (
"github.com/hashicorp/golang-lru" "github.com/hashicorp/golang-lru"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/util" "github.com/syndtr/goleveldb/leveldb/util"
"os"
"os/signal"
"runtime"
"sync"
"sync/atomic"
"time"
) )
var ( var (
dir = flag.String("dir", "", "dir to mainet chain data") dir = flag.String("dir", "", "directory to XDCChain chaindata")
cacheSize = flag.Int("size", 1000000, "dir to mainet chain data") 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 { type TrieRoot struct {
@ -42,14 +50,6 @@ type ResultProcessNode struct {
keys [17]*[]byte 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() { func main() {
flag.Parse() flag.Parse()
lddb, _ := ethdb.NewLDBDatabase(*dir, eth.DefaultConfig.DatabaseCache, utils.MakeDatabaseHandles()) lddb, _ := ethdb.NewLDBDatabase(*dir, eth.DefaultConfig.DatabaseCache, utils.MakeDatabaseHandles())

View file

@ -122,8 +122,8 @@ func (w *wizard) makeGenesis() {
genesis.Config.XDPoS.Period = uint64(w.readDefaultInt(2)) genesis.Config.XDPoS.Period = uint64(w.readDefaultInt(2))
fmt.Println() fmt.Println()
fmt.Println("How many XDC should be rewarded to masternode? (default = 100)") fmt.Println("How many XDC should be rewarded to masternode? (default = 350)")
genesis.Config.XDPoS.Reward = uint64(w.readDefaultInt(100)) genesis.Config.XDPoS.Reward = uint64(w.readDefaultInt(350))
fmt.Println() fmt.Println()
fmt.Println("Who own the first masternodes? (mandatory)") fmt.Println("Who own the first masternodes? (mandatory)")
@ -231,8 +231,8 @@ func (w *wizard) makeGenesis() {
code, _ = contractBackend.CodeAt(ctx, multiSignWalletAddr, nil) code, _ = contractBackend.CodeAt(ctx, multiSignWalletAddr, nil)
storage = make(map[common.Hash]common.Hash) storage = make(map[common.Hash]common.Hash)
contractBackend.ForEachStorageAt(ctx, multiSignWalletAddr, nil, f) contractBackend.ForEachStorageAt(ctx, multiSignWalletAddr, nil, f)
fBalance := big.NewInt(0) // 16m fBalance := big.NewInt(0) // 3 billion
fBalance.Add(fBalance, big.NewInt(16*1000*1000)) fBalance.Add(fBalance, big.NewInt(3*1000*1000*1000))
fBalance.Mul(fBalance, big.NewInt(1000000000000000000)) fBalance.Mul(fBalance, big.NewInt(1000000000000000000))
genesis.Alloc[common.HexToAddress(common.FoudationAddr)] = core.GenesisAccount{ genesis.Alloc[common.HexToAddress(common.FoudationAddr)] = core.GenesisAccount{
Balance: fBalance, Balance: fBalance,
@ -298,24 +298,24 @@ func (w *wizard) makeGenesis() {
storage = make(map[common.Hash]common.Hash) storage = make(map[common.Hash]common.Hash)
contractBackend.ForEachStorageAt(ctx, multiSignWalletTeamAddr, nil, f) contractBackend.ForEachStorageAt(ctx, multiSignWalletTeamAddr, nil, f)
// Team balance. // Team balance.
balance := big.NewInt(0) // 12m balance := big.NewInt(0) // 20 billion
balance.Add(balance, big.NewInt(12*1000*1000)) balance.Add(balance, big.NewInt(20*1000*1000*1000))
balance.Mul(balance, big.NewInt(1000000000000000000)) balance.Mul(balance, big.NewInt(1000000000000000000))
subBalance := big.NewInt(0) // i * 50k subBalance := big.NewInt(0) // i * 50k
subBalance.Add(subBalance, big.NewInt(int64(len(signers))*50*1000)) subBalance.Add(subBalance, big.NewInt(int64(len(signers))*50*1000))
subBalance.Mul(subBalance, big.NewInt(1000000000000000000)) subBalance.Mul(subBalance, big.NewInt(1000000000000000000))
balance.Sub(balance, subBalance) // 12m - i * 50k balance.Sub(balance, subBalance) // 12m - i * 50k
genesis.Alloc[common.HexToAddress(common.TeamAddr)] = core.GenesisAccount{ genesis.Alloc[common.HexToAddress(common.TeamAddr)] = core.GenesisAccount{
Balance: balance, Balance: balance,
Code: code, Code: code,
Storage: storage, Storage: storage,
} }
fmt.Println() 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() swapAddr := *w.readAddress()
baseBalance := big.NewInt(0) // 55m baseBalance := big.NewInt(0) // 14.5Billion
baseBalance.Add(baseBalance, big.NewInt(55*1000*1000)) baseBalance.Add(baseBalance, big.NewInt(145*1000*1000*100))
baseBalance.Mul(baseBalance, big.NewInt(1000000000000000000)) baseBalance.Mul(baseBalance, big.NewInt(1000000000000000000))
genesis.Alloc[swapAddr] = core.GenesisAccount{ genesis.Alloc[swapAddr] = core.GenesisAccount{
Balance: baseBalance, Balance: baseBalance,

View file

@ -22,8 +22,9 @@ const (
MinimunMinerBlockPerEpoch = 1 MinimunMinerBlockPerEpoch = 1
) )
var TIP2019Block = big.NewInt(1050000) var TIP2019Block = big.NewInt(1)
var TIPSigning = big.NewInt(3000000) var TIPSigning = big.NewInt(3000000)
var TIPRandomize = big.NewInt(3464000)
var IsTestnet bool = false var IsTestnet bool = false
var StoreRewardFolder string var StoreRewardFolder string
var RollbackHash Hash var RollbackHash Hash

View file

@ -13,7 +13,7 @@
// You should have received a copy of the GNU Lesser General Public License // 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/>. // 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 package XDPoS
import ( import (
@ -25,6 +25,8 @@ import (
"math/big" "math/big"
"math/rand" "math/rand"
"path/filepath" "path/filepath"
"reflect"
"sort"
"strconv" "strconv"
"sync" "sync"
"time" "time"
@ -58,7 +60,7 @@ type Masternode struct {
Stake *big.Int Stake *big.Int
} }
// XDPoS delegated-proof-of-stake protocol constants. // XDPoS proof-of-stake-voting protocol constants.
var ( var (
epochLength = uint64(900) // Default number of blocks after which to checkpoint and reset the pending votes epochLength = uint64(900) // Default number of blocks after which to checkpoint and reset the pending votes
@ -149,7 +151,7 @@ var (
// backing account. // backing account.
//type SignerFn func(accounts.Account, []byte) ([]byte, error) //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 // signing. It is the hash of the entire header apart from the 65 byte signature
// contained at the end of the extra data. // 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 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. // Ethereum testnet following the Ropsten attacks.
type XDPoS struct { type XDPoS struct {
config *params.XDPoSConfig // Consensus engine configuration parameters config *params.XDPoSConfig // Consensus engine configuration parameters
@ -225,15 +227,15 @@ type XDPoS struct {
signFn clique.SignerFn // Signer function to authorize hashes with signFn clique.SignerFn // Signer function to authorize hashes with
lock sync.RWMutex // Protects the signer fields lock sync.RWMutex // Protects the signer fields
BlockSigners *lru.Cache BlockSigners *lru.Cache
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) 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) HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]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) HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
HookVerifyMNs func(header *types.Header, signers []common.Address) 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. // signers set to the ones provided by the user.
func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS { func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
// Set any missing consensus parameters to their defaults // 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) signers = RemovePenaltiesFromBlock(chain, signers, number-uint64(i)*c.config.Epoch)
} }
} }
byteMasterNodes := common.ExtractAddressToBytes(signers)
extraSuffix := len(header.Extra) - extraSeal 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 return errInvalidCheckpointSigners
} }
if c.HookVerifyMNs != nil { if c.HookVerifyMNs != nil {
@ -440,6 +444,21 @@ func (c *XDPoS) verifyCascadingFields(chain consensus.ChainReader, header *types
return c.verifySeal(chain, header, parents, fullVerify) 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) { func (c *XDPoS) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*Snapshot, error) {
number := header.Number.Uint64() number := header.Number.Uint64()
log.Trace("take snapshot", "number", number, "hash", header.Hash()) 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") return common.Address{}, fmt.Errorf("couldn't find checkpoint header")
} }
} }
m, err := GetM1M2FromCheckpointHeader(cpHeader) m, err := GetM1M2FromCheckpointHeader(cpHeader, header, chain.Config())
if err != nil { if err != nil {
return common.Address{}, err return common.Address{}, err
} }
@ -977,7 +996,13 @@ func (c *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, stop <-cha
return nil, err return nil, err
} }
copy(header.Extra[len(header.Extra)-extraSeal:], sighash) 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 return block.WithSeal(header), nil
} }
@ -1119,26 +1144,41 @@ func GetMasternodesFromCheckpointHeader(checkpointHeader *types.Header) []common
} }
// Get m2 list from checkpoint block. // 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 { if checkpointHeader.Number.Uint64()%common.EpocBlockRandomize != 0 {
return nil, errors.New("This block is not checkpoint block epoc.") return nil, errors.New("This block is not checkpoint block epoc.")
} }
m1m2 := map[common.Address]common.Address{}
// Get signers from this block. // Get signers from this block.
masternodes := GetMasternodesFromCheckpointHeader(checkpointHeader) masternodes := GetMasternodesFromCheckpointHeader(checkpointHeader)
validators := ExtractValidatorsFromBytes(checkpointHeader.Validators) validators := ExtractValidatorsFromBytes(checkpointHeader.Validators)
m1m2, _, err := getM1M2(masternodes, validators, currentHeader, config)
if len(validators) < len(masternodes) { if err != nil {
return nil, errors.New("len(m2) is less than len(m1)") return map[common.Address]common.Address{}, err
}
if len(masternodes) > 0 {
for i, m1 := range masternodes {
m1m2[m1] = masternodes[validators[i]%int64(len(masternodes))]
}
} }
return m1m2, nil 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. // Extract validators from byte array.
func ExtractValidatorsFromBytes(byteValidators []byte) []int64 { func ExtractValidatorsFromBytes(byteValidators []byte) []int64 {
lenValidator := len(byteValidators) / M2ByteLength lenValidator := len(byteValidators) / M2ByteLength

View 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 := &params.ChainConfig{
XDPoS: &params.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")
}
}

View file

@ -35,7 +35,7 @@ package contracts
// "randomSecret": 0, // "randomSecret": 0,
// "randomOpening": 1, // "randomOpening": 1,
// } // }
// datadir = "/mnt/sgp1_tuna_chaindata3/data/XDCchaindata" // datadir = "/mnt/sgp1_tuna_chaindata3/data/XDC/chaindata"
// candidate = "0xd6fa3e7a89bf8c84f0ccd204a15c0d259daf2091" // candidate = "0xd6fa3e7a89bf8c84f0ccd204a15c0d259daf2091"
//) //)
// //

View file

@ -464,7 +464,7 @@ func GetRewardBalancesRate(foundationWalletAddr common.Address, state *state.Sta
log.Error("Fail to parse json holders", "error", err) log.Error("Fail to parse json holders", "error", err)
return nil, 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 return balances, nil
} }
@ -503,7 +503,8 @@ func Encrypt(key []byte, text string) string {
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { 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 // 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)) ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize] iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(cryptoRand.Reader, iv); err != nil { 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) stream := cipher.NewCFBEncrypter(block, iv)
@ -527,13 +529,15 @@ func Decrypt(key []byte, cryptoText string) string {
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { 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 // The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext. // include it at the beginning of the ciphertext.
if len(ciphertext) < aes.BlockSize { if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short") log.Error("ciphertext too short")
return ""
} }
iv := ciphertext[:aes.BlockSize] iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:] ciphertext = ciphertext[aes.BlockSize:]

View file

@ -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) owner := GetCandidatesOwnerBySigner(validator, masterAddr)
balances := make(map[common.Address]*big.Int) balances := make(map[common.Address]*big.Int)
rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent)) rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent))

View 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" \
"$@"

View file

@ -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) { c.HookPenaltyTIPSigning = func(chain consensus.ChainReader, header *types.Header, candidates []common.Address) ([]common.Address, error) {
prevEpoc := header.Number.Uint64() - chain.Config().XDPoS.Epoch prevEpoc := header.Number.Uint64() - chain.Config().XDPoS.Epoch
combackEpoch := uint64(0) 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 { if header.Number.Uint64() > comebackLength {
combackEpoch = header.Number.Uint64() - comebackLength combackEpoch = header.Number.Uint64() - comebackLength
} }
@ -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))) 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...) penalties = append(penalties, penComebacks...)
if chain.Config().IsTIPRandomize(header.Number) {
return penalties, nil
}
return penComebacks, nil return penComebacks, nil
} }
return []common.Address{}, nil return []common.Address{}, nil
} }

View file

@ -90,6 +90,7 @@ var (
errCancelContentProcessing = errors.New("content processing canceled (requested)") errCancelContentProcessing = errors.New("content processing canceled (requested)")
errNoSyncActive = errors.New("no sync active") errNoSyncActive = errors.New("no sync active")
errTooOld = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)") errTooOld = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)")
errEnoughBlock = errors.New("downloader download enough block")
) )
type Downloader struct { type Downloader struct {
@ -421,7 +422,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
}(time.Now()) }(time.Now())
// Look up the sync boundaries: the common ancestor and the target block // 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 { if err != nil {
return err return err
} }
@ -469,7 +470,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
if d.mode == FastSync { if d.mode == FastSync {
fetchers = append(fetchers, func() error { return d.processFastSyncContent(latest) }) fetchers = append(fetchers, func() error { return d.processFastSyncContent(latest) })
} else if d.mode == FullSync { } else if d.mode == FullSync {
fetchers = append(fetchers, d.processFullSyncContent) fetchers = append(fetchers, func() error { return d.processFullSyncContent(height) })
} }
return d.spawnSync(fetchers) return d.spawnSync(fetchers)
} }
@ -500,6 +501,9 @@ func (d *Downloader) spawnSync(fetchers []func() error) error {
d.queue.Close() d.queue.Close()
d.Cancel() d.Cancel()
wg.Wait() wg.Wait()
if err == errEnoughBlock {
return nil
}
return err return err
} }
@ -537,12 +541,10 @@ func (d *Downloader) Terminate() {
// fetchHeight retrieves the head header of the remote peer to aid in estimating // fetchHeight retrieves the head header of the remote peer to aid in estimating
// the total time a pending synchronisation would take. // the total time a pending synchronisation would take.
func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) { func (d *Downloader) fetchHeight(p *peerConnection, hash common.Hash) (*types.Header, error) {
p.log.Debug("Retrieving remote chain height")
// Request the advertised remote head block and wait for the response // Request the advertised remote head block and wait for the response
head, _ := p.peer.Head() go p.peer.RequestHeadersByHash(hash, 1, 0, false)
go p.peer.RequestHeadersByHash(head, 1, 0, false)
ttl := d.requestTTL() ttl := d.requestTTL()
timeout := time.After(ttl) 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. // 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 { for {
results := d.queue.Results(true) results := d.queue.Results(true)
if len(results) == 0 { if len(results) == 0 {
@ -1358,6 +1360,11 @@ func (d *Downloader) processFullSyncContent() error {
return err 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
}
} }
} }

View file

@ -542,9 +542,9 @@ func hasXDCPrefix(str string) bool {
} }
func decodeAddress(s string) (common.Address, error) { func decodeAddress(s string) (common.Address, error) {
if hasXDCPrefix(s) { if hasXDCPrefix(s) {
s = "0x" + s[3:] s = "0x" + s[3:]
} }
b, err := hexutil.Decode(s) b, err := hexutil.Decode(s)
if err == nil && len(b) != common.AddressLength { if err == nil && len(b) != common.AddressLength {
err = fmt.Errorf("hex has invalid length %d after decoding", len(b)) err = fmt.Errorf("hex has invalid length %d after decoding", len(b))

View file

@ -17,7 +17,7 @@
} }
}, },
"nonce": "0x0", "nonce": "0x0",
"timestamp": "0x5c107ff8", "timestamp": "0x5c1358f5",
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000001b82c4bf317fcafe3d77e8b444c82715d216afe845b7bd987fa22c9bac89b71f0ded03f6e150ba31ad670b2b166684657ffff95f4810380ae7381e9bce41231d5dd8cdd7499e418b648c00af75d184a2f9aba09a6fa4a46fb1a6a3919b027d9cac5aa6890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "extraData": "0x00000000000000000000000000000000000000000000000000000000000000001b82c4bf317fcafe3d77e8b444c82715d216afe845b7bd987fa22c9bac89b71f0ded03f6e150ba31ad670b2b166684657ffff95f4810380ae7381e9bce41231d5dd8cdd7499e418b648c00af75d184a2f9aba09a6fa4a46fb1a6a3919b027d9cac5aa6890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x47b760", "gasLimit": "0x47b760",
"difficulty": "0x1", "difficulty": "0x1",

View file

@ -22,10 +22,12 @@ import (
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"sort"
"strings" "strings"
"time" "time"
"github.com/ethereum/go-ethereum/accounts" "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/accounts/keystore"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "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/ethash"
"github.com/ethereum/go-ethereum/consensus/XDPoS" "github.com/ethereum/go-ethereum/consensus/XDPoS"
"github.com/ethereum/go-ethereum/contracts" "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"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
@ -44,17 +47,14 @@ import (
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/util" "github.com/syndtr/goleveldb/leveldb/util"
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
) )
const ( const (
defaultGasPrice = 50 * params.Shannon defaultGasPrice = 50 * params.Shannon
// statuses of candidates // statuses of candidates
statusMasternode = "MASTERNODE" statusMasternode = "MASTERNODE"
statusSlashed = "SLASHED" statusSlashed = "SLASHED"
statusProposed = "PROPOSED" statusProposed = "PROPOSED"
) )
// PublicEthereumAPI provides an API to access Ethereum related information. // 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 return masternodes, nil
} }
// GetCandidateStatus returns status of the given candidate at a specified epochNumber // 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) { func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAddress common.Address, epochNumber rpc.EpochNumber) (string, error) {
var ( var (
block *types.Block block *types.Block
masternodes, penaltyList, candidates, proposedList []common.Address masternodes, penaltyList []common.Address
penalties []byte penalties []byte
err error err error
) )
block = s.b.CurrentBlock() block = s.b.CurrentBlock()
epoch := s.b.ChainConfig().XDPoS.Epoch 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 // read smart contract to get candidate list
client, err := s.b.GetIPCClient() client, err := s.b.GetIPCClient()
if err != nil { if err != nil {
@ -767,21 +745,64 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
return "", err return "", err
} }
opts := new(bind.CallOpts) opts := new(bind.CallOpts)
candidates, err = validator.GetCandidates(opts) var (
candidateAddresses []common.Address
candidates []XDPoS.Masternode
)
candidateAddresses, err = validator.GetCandidates(opts)
if err != nil { if err != nil {
return "", err return "", err
} }
// exclude masternodes for _, address := range candidateAddresses {
proposedList = common.RemoveItemFromArray(candidates, masternodes) v, err := validator.GetCandidateCap(opts, address)
// exclude penalties if err != nil {
proposedList = common.RemoveItemFromArray(proposedList, penaltyList) return "", err
}
for _, proposed := range proposedList { if address.String() != "xdc0000000000000000000000000000000000000000" {
if coinbaseAddress == proposed { candidates = append(candidates, XDPoS.Masternode{Address: address, Stake: v})
return statusProposed, nil
} }
} }
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. // CallArgs represents the arguments for a call.

View file

@ -56,7 +56,7 @@ const (
// timeout waiting for M1 // timeout waiting for M1
waitPeriod = 10 waitPeriod = 10
// timeout for checkpoint. // timeout for checkpoint.
waitPeriodCheckpoint = 120 // 2 mins waitPeriodCheckpoint = 20
) )
// Agent can register themself with the worker // Agent can register themself with the worker
@ -330,7 +330,7 @@ func (self *worker) wait() {
continue continue
} }
block := result.Block 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}) self.mux.Post(core.NewMinedBlockEvent{Block: block})
continue continue
} }

View file

@ -89,7 +89,7 @@ var (
// //
// This configuration is intentionally not using keyed fields to force anyone // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // 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} 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} 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)) TestRules = TestChainConfig.Rules(new(big.Int))
@ -121,7 +121,7 @@ type ChainConfig struct {
// Various consensus engines // Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"` Ethash *EthashConfig `json:"ethash,omitempty"`
Clique *CliqueConfig `json:"clique,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. // 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) 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). // 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. // The returned GasTable's fields shouldn't, under any circumstances, be changed.

View file

@ -21,9 +21,9 @@ import (
) )
const ( const (
VersionMajor = 0 // Major version component of the current release VersionMajor = 0 // Major version component of the current release
VersionMinor = 5 // Minor version component of the current release VersionMinor = 5 // Minor version component of the current release
VersionPatch = 0 // Patch 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 VersionMeta = "stable" // Version metadata to append to the version string
) )

View file

@ -190,14 +190,14 @@ func (s *Server) serveRequest(codec ServerCodec, singleShot bool, options CodecO
if singleShot { if singleShot {
if batch { if batch {
for _, req := range reqs { 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"})) codec.Write(codec.CreateErrorResponse(&req.id, &invalidRequestError{message: "Only support send transaction with ipc"}))
return nil return nil
} }
} }
s.execBatch(ctx, codec, reqs) s.execBatch(ctx, codec, reqs)
} else { } 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"})) codec.Write(codec.CreateErrorResponse(&reqs[0].id, &invalidRequestError{message: "Only support send transaction with ipc"}))
return nil return nil
} }

View file

@ -123,7 +123,7 @@ const (
PendingBlockNumber = BlockNumber(-2) PendingBlockNumber = BlockNumber(-2)
LatestBlockNumber = BlockNumber(-1) LatestBlockNumber = BlockNumber(-1)
EarliestBlockNumber = BlockNumber(0) EarliestBlockNumber = BlockNumber(0)
LatestEpochNumber = EpochNumber(-1) LatestEpochNumber = EpochNumber(-1)
) )
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports: // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:

File diff suppressed because one or more lines are too long