mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-24 07:34:31 +00:00
Merge pull request #12 from hash-laboratories-au/adaptor-config-setup-with-tests
Adaptor config setup with tests
This commit is contained in:
commit
a996c3a1a3
23 changed files with 900 additions and 31233 deletions
|
|
@ -70,18 +70,18 @@ type SimulatedBackend struct {
|
|||
}
|
||||
|
||||
// XDC simulated backend for testing purpose.
|
||||
func NewXDCSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
|
||||
func NewXDCSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64, chainConfig *params.ChainConfig) *SimulatedBackend {
|
||||
// database := ethdb.NewMemDatabase()
|
||||
database := rawdb.NewMemoryDatabase()
|
||||
|
||||
genesis := core.Genesis{
|
||||
GasLimit: gasLimit, // need this big, support initial smart contract
|
||||
Config: params.TestXDPoSMockChainConfig,
|
||||
Config: chainConfig,
|
||||
Alloc: alloc,
|
||||
ExtraData: append(make([]byte, 32), make([]byte, 65)...),
|
||||
}
|
||||
genesis.MustCommit(database)
|
||||
consensus := XDPoS.NewFaker(database)
|
||||
consensus := XDPoS.NewFaker(database, chainConfig)
|
||||
|
||||
// Attach mock trading and lending service
|
||||
var DefaultConfig = XDCx.Config{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
|
|
@ -229,7 +230,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy an interaction tester contract and call a transaction on it
|
||||
_, _, interactor, err := DeployInteractor(auth, sim, "Deploy string")
|
||||
|
|
@ -270,7 +271,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a tuple tester contract and execute a structured call on it
|
||||
_, _, getter, err := DeployGetter(auth, sim)
|
||||
|
|
@ -302,7 +303,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a tuple tester contract and execute a structured call on it
|
||||
_, _, tupler, err := DeployTupler(auth, sim)
|
||||
|
|
@ -344,7 +345,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a slice tester contract and execute a n array call on it
|
||||
_, _, slicer, err := DeploySlicer(auth, sim)
|
||||
|
|
@ -378,7 +379,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a default method invoker contract and execute its default method
|
||||
_, _, defaulter, err := DeployDefaulter(auth, sim)
|
||||
|
|
@ -411,7 +412,7 @@ var bindTests = []struct {
|
|||
`[{"constant":true,"inputs":[],"name":"String","outputs":[{"name":"","type":"string"}],"type":"function"}]`,
|
||||
`
|
||||
// Create a simulator and wrap a non-deployed contract
|
||||
sim := backends.NewXDCSimulatedBackend(nil, uint64(10000000000))
|
||||
sim := backends.NewXDCSimulatedBackend(nil, uint64(10000000000), params.TestXDPoSMockChainConfig)
|
||||
|
||||
nonexistent, err := NewNonExistent(common.Address{}, sim)
|
||||
if err != nil {
|
||||
|
|
@ -447,7 +448,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a funky gas pattern contract
|
||||
_, _, limiter, err := DeployFunkyGasPattern(auth, sim)
|
||||
|
|
@ -482,7 +483,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a sender tester contract and execute a structured call on it
|
||||
_, _, callfrom, err := DeployCallFrom(auth, sim)
|
||||
|
|
@ -542,7 +543,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a underscorer tester contract and execute a structured call on it
|
||||
_, _, underscorer, err := DeployUnderscorer(auth, sim)
|
||||
|
|
@ -612,7 +613,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy an eventer contract
|
||||
_, _, eventer, err := DeployEventer(auth, sim)
|
||||
|
|
@ -761,7 +762,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
//deploy the test contract
|
||||
_, _, testContract, err := DeployDeeplyNestedArray(auth, sim)
|
||||
|
|
@ -819,6 +820,7 @@ func TestBindings(t *testing.T) {
|
|||
if !common.FileExist(gocmd) {
|
||||
t.Skip("go sdk not found for testing")
|
||||
}
|
||||
t.Log("Using config", params.TestXDPoSMockChainConfig)
|
||||
// Skip the test if the go-ethereum sources are symlinked (https://github.com/golang/go/issues/14845)
|
||||
linkTestCode := fmt.Sprintf("package linktest\nfunc CheckSymlinks(){\nfmt.Println(backends.NewSimulatedBackend(nil))\n}")
|
||||
linkTestDeps, err := imports.Process(os.TempDir(), []byte(linkTestCode), nil)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
|
|
@ -56,7 +57,7 @@ func TestWaitDeployed(t *testing.T) {
|
|||
backend := backends.NewXDCSimulatedBackend(
|
||||
core.GenesisAlloc{
|
||||
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
|
||||
}, 10000000,
|
||||
}, 10000000, params.TestXDPoSMockChainConfig,
|
||||
)
|
||||
|
||||
// Create the transaction.
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ func (w *wizard) makeGenesis() {
|
|||
// Validator Smart Contract Code
|
||||
pKey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
addr := crypto.PubkeyToAddress(pKey.PublicKey)
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000)
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
transactOpts := bind.NewKeyedTransactor(pKey)
|
||||
|
||||
validatorAddress, _, err := validatorContract.DeployValidator(transactOpts, contractBackend, signers, validatorCaps, owner)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/engines/engine_v1"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/engines/engine_v2"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
|
|
@ -34,11 +36,7 @@ import (
|
|||
)
|
||||
|
||||
func SigHash(header *types.Header) (hash common.Hash) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
// TODO: Add switch case for 2.0 later
|
||||
default: // Default "1.0"
|
||||
return engine_v1.SigHash(header)
|
||||
}
|
||||
return utils.SigHash(header)
|
||||
}
|
||||
|
||||
// XDPoS is the delegated-proof-of-stake consensus engine proposed to support the
|
||||
|
|
@ -56,6 +54,7 @@ type XDPoS struct {
|
|||
|
||||
// The exact consensus engine with different versions
|
||||
EngineV1 engine_v1.XDPoS_v1
|
||||
EngineV2 engine_v2.XDPoS_v2
|
||||
}
|
||||
|
||||
// New creates a XDPoS delegated-proof-of-stake consensus engine with the initial
|
||||
|
|
@ -72,26 +71,34 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
|
|||
|
||||
return &XDPoS{
|
||||
config: &conf,
|
||||
db: db,
|
||||
|
||||
signingTxsCache: signingTxsCache,
|
||||
EngineV1: *engine_v1.New(&conf, db),
|
||||
EngineV2: *engine_v2.New(&conf, db),
|
||||
}
|
||||
}
|
||||
|
||||
// NewFullFaker creates an ethash consensus engine with a full fake scheme that
|
||||
// accepts all blocks as valid, without checking any consensus rules whatsoever.
|
||||
func NewFaker(db ethdb.Database) *XDPoS {
|
||||
func NewFaker(db ethdb.Database, chainConfig *params.ChainConfig) *XDPoS {
|
||||
var fakeEngine *XDPoS
|
||||
// Set any missing consensus parameters to their defaults
|
||||
conf := params.TestXDPoSMockChainConfig.XDPoS
|
||||
if chainConfig != nil {
|
||||
conf = chainConfig.XDPoS
|
||||
}
|
||||
|
||||
// Allocate the snapshot caches and create the engine
|
||||
signingTxsCache, _ := lru.New(utils.BlockSignersCacheLimit)
|
||||
|
||||
fakeEngine = &XDPoS{
|
||||
config: conf,
|
||||
db: db,
|
||||
|
||||
signingTxsCache: signingTxsCache,
|
||||
EngineV1: *engine_v1.NewFaker(db),
|
||||
EngineV1: *engine_v1.NewFaker(db, conf),
|
||||
EngineV2: *engine_v2.NewFaker(db, conf),
|
||||
}
|
||||
return fakeEngine
|
||||
}
|
||||
|
|
@ -101,92 +108,94 @@ func NewFaker(db ethdb.Database) *XDPoS {
|
|||
*/
|
||||
// APIs implements consensus.Engine, returning the user facing RPC API to allow
|
||||
// controlling the signer voting.
|
||||
func (c *XDPoS) APIs(chain consensus.ChainReader) []rpc.API {
|
||||
func (x *XDPoS) APIs(chain consensus.ChainReader) []rpc.API {
|
||||
return []rpc.API{{
|
||||
Namespace: "XDPoS",
|
||||
Version: "1.0",
|
||||
Service: &API{chain: chain, XDPoS: c},
|
||||
Service: &API{chain: chain, XDPoS: x},
|
||||
Public: true,
|
||||
}}
|
||||
}
|
||||
|
||||
// Author implements consensus.Engine, returning the Ethereum address recovered
|
||||
// from the signature in the header's extra-data section.
|
||||
func (c *XDPoS) Author(header *types.Header) (common.Address, error) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.Author(header)
|
||||
func (x *XDPoS) Author(header *types.Header) (common.Address, error) {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
case params.ConsensusEngineVersion2:
|
||||
return x.EngineV2.Author(header)
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.Author(header)
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyHeader checks whether a header conforms to the consensus rules.
|
||||
func (c *XDPoS) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.VerifyHeader(chain, header, fullVerify)
|
||||
func (x *XDPoS) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.VerifyHeader(chain, header, fullVerify)
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
|
||||
// method returns a quit channel to abort the operations and a results channel to
|
||||
// retrieve the async verifications (the order is that of the input slice).
|
||||
func (c *XDPoS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
|
||||
func (x *XDPoS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
|
||||
// TODO: (Hashlab) This funciton is a special case
|
||||
return c.EngineV1.VerifyHeaders(chain, headers, fullVerifies)
|
||||
return x.EngineV1.VerifyHeaders(chain, headers, fullVerifies)
|
||||
}
|
||||
|
||||
// VerifyUncles implements consensus.Engine, always returning an error for any
|
||||
// uncles as this consensus mechanism doesn't permit uncles.
|
||||
func (c *XDPoS) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
||||
switch params.BlockConsensusVersion(block.Number()) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.VerifyUncles(chain, block)
|
||||
func (x *XDPoS) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
||||
switch x.config.BlockConsensusVersion(block.Number()) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.VerifyUncles(chain, block)
|
||||
}
|
||||
}
|
||||
|
||||
// VerifySeal implements consensus.Engine, checking whether the signature contained
|
||||
// in the header satisfies the consensus protocol requirements.
|
||||
func (c *XDPoS) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.VerifySeal(chain, header)
|
||||
func (x *XDPoS) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.VerifySeal(chain, header)
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare implements consensus.Engine, preparing all the consensus fields of the
|
||||
// header for running the transactions on top.
|
||||
func (c *XDPoS) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.Prepare(chain, header)
|
||||
func (x *XDPoS) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.Prepare(chain, header)
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||
// rewards given, and returns the final block.
|
||||
func (c *XDPoS) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.Finalize(chain, header, state, parentState, txs, uncles, receipts)
|
||||
func (x *XDPoS) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.Finalize(chain, header, state, parentState, txs, uncles, receipts)
|
||||
}
|
||||
}
|
||||
|
||||
// Seal implements consensus.Engine, attempting to create a sealed block using
|
||||
// the local signing credentials.
|
||||
func (c *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
|
||||
switch params.BlockConsensusVersion(block.Number()) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.Seal(chain, block, stop)
|
||||
func (x *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
|
||||
switch x.config.BlockConsensusVersion(block.Number()) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.Seal(chain, block, stop)
|
||||
}
|
||||
}
|
||||
|
||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
||||
// that a new block should have based on the previous blocks in the chain and the
|
||||
// current signer.
|
||||
func (c *XDPoS) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
|
||||
switch params.BlockConsensusVersion(parent.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.CalcDifficulty(chain, time, parent)
|
||||
func (x *XDPoS) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
|
||||
switch x.config.BlockConsensusVersion(parent.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.CalcDifficulty(chain, time, parent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,81 +205,81 @@ func (c *XDPoS) CalcDifficulty(chain consensus.ChainReader, time uint64, parent
|
|||
|
||||
// Authorize injects a private key into the consensus engine to mint new blocks
|
||||
// with.
|
||||
func (c *XDPoS) Authorize(signer common.Address, signFn clique.SignerFn) {
|
||||
func (x *XDPoS) Authorize(signer common.Address, signFn clique.SignerFn) {
|
||||
// Authorize each consensus individually
|
||||
c.EngineV1.Authorize(signer, signFn)
|
||||
x.EngineV1.Authorize(signer, signFn)
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetPeriod() uint64 {
|
||||
return c.config.Period
|
||||
func (x *XDPoS) GetPeriod() uint64 {
|
||||
return x.config.Period
|
||||
}
|
||||
|
||||
func (c *XDPoS) IsAuthorisedAddress(header *types.Header, chain consensus.ChainReader, address common.Address) bool {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.IsAuthorisedAddress(header, chain, address)
|
||||
func (x *XDPoS) IsAuthorisedAddress(header *types.Header, chain consensus.ChainReader, address common.Address) bool {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.IsAuthorisedAddress(header, chain, address)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.GetMasternodes(chain, header)
|
||||
func (x *XDPoS) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.GetMasternodes(chain, header)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (int, int, int, bool, error) {
|
||||
switch params.BlockConsensusVersion(parent.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.YourTurn(chain, parent, signer)
|
||||
func (x *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (int, int, int, bool, error) {
|
||||
switch x.config.BlockConsensusVersion(parent.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.YourTurn(chain, parent, signer)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetValidator(creator common.Address, chain consensus.ChainReader, header *types.Header) (common.Address, error) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.GetValidator(creator, chain, header)
|
||||
func (x *XDPoS) GetValidator(creator common.Address, chain consensus.ChainReader, header *types.Header) (common.Address, error) {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.GetValidator(creator, chain, header)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []utils.Masternode) error {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.UpdateMasternodes(chain, header, ms)
|
||||
func (x *XDPoS) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []utils.Masternode) error {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.UpdateMasternodes(chain, header, ms)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) RecoverSigner(header *types.Header) (common.Address, error) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.RecoverSigner(header)
|
||||
func (x *XDPoS) RecoverSigner(header *types.Header) (common.Address, error) {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.RecoverSigner(header)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) RecoverValidator(header *types.Header) (common.Address, error) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.RecoverValidator(header)
|
||||
func (x *XDPoS) RecoverValidator(header *types.Header) (common.Address, error) {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.RecoverValidator(header)
|
||||
}
|
||||
}
|
||||
|
||||
// Get master nodes over extra data of previous checkpoint block.
|
||||
func (c *XDPoS) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Header, n, e uint64) []common.Address {
|
||||
switch params.BlockConsensusVersion(preCheckpointHeader.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.GetMasternodesFromCheckpointHeader(preCheckpointHeader, n, e)
|
||||
func (x *XDPoS) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Header, n, e uint64) []common.Address {
|
||||
switch x.config.BlockConsensusVersion(preCheckpointHeader.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.GetMasternodesFromCheckpointHeader(preCheckpointHeader, n, e)
|
||||
}
|
||||
}
|
||||
|
||||
// Same DB across all consensus engines
|
||||
func (c *XDPoS) GetDb() ethdb.Database {
|
||||
return c.db
|
||||
func (x *XDPoS) GetDb() ethdb.Database {
|
||||
return x.db
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*utils.PublicApiSnapshot, error) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
sp, err := c.EngineV1.GetSnapshot(chain, header)
|
||||
func (x *XDPoS) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*utils.PublicApiSnapshot, error) {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
sp, err := x.EngineV1.GetSnapshot(chain, header)
|
||||
// Convert to a standard PublicApiSnapshot type, otherwise it's a breaking change to API
|
||||
return &utils.PublicApiSnapshot{
|
||||
Number: sp.Number,
|
||||
|
|
@ -283,10 +292,10 @@ func (c *XDPoS) GetSnapshot(chain consensus.ChainReader, header *types.Header) (
|
|||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, header *types.Header) ([]common.Address, error) {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.GetAuthorisedSignersFromSnapshot(chain, header)
|
||||
func (x *XDPoS) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, header *types.Header) ([]common.Address, error) {
|
||||
switch x.config.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "v1"
|
||||
return x.EngineV1.GetAuthorisedSignersFromSnapshot(chain, header)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -295,7 +304,7 @@ Caching
|
|||
*/
|
||||
|
||||
// Cache signing transaction data into BlockSingers cache object
|
||||
func (c *XDPoS) CacheNoneTIPSigningTxs(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) []*types.Transaction {
|
||||
func (x *XDPoS) CacheNoneTIPSigningTxs(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) []*types.Transaction {
|
||||
signTxs := []*types.Transaction{}
|
||||
for _, tx := range txs {
|
||||
if tx.IsSigningTransaction() {
|
||||
|
|
@ -320,13 +329,13 @@ func (c *XDPoS) CacheNoneTIPSigningTxs(header *types.Header, txs []*types.Transa
|
|||
}
|
||||
|
||||
log.Debug("Save tx signers to cache", "hash", header.Hash().String(), "number", header.Number, "len(txs)", len(signTxs))
|
||||
c.signingTxsCache.Add(header.Hash(), signTxs)
|
||||
x.signingTxsCache.Add(header.Hash(), signTxs)
|
||||
|
||||
return signTxs
|
||||
}
|
||||
|
||||
// Cache
|
||||
func (c *XDPoS) CacheSigningTxs(hash common.Hash, txs []*types.Transaction) []*types.Transaction {
|
||||
func (x *XDPoS) CacheSigningTxs(hash common.Hash, txs []*types.Transaction) []*types.Transaction {
|
||||
signTxs := []*types.Transaction{}
|
||||
for _, tx := range txs {
|
||||
if tx.IsSigningTransaction() {
|
||||
|
|
@ -334,10 +343,10 @@ func (c *XDPoS) CacheSigningTxs(hash common.Hash, txs []*types.Transaction) []*t
|
|||
}
|
||||
}
|
||||
log.Debug("Save tx signers to cache", "hash", hash.String(), "len(txs)", len(signTxs))
|
||||
c.signingTxsCache.Add(hash, signTxs)
|
||||
x.signingTxsCache.Add(hash, signTxs)
|
||||
return signTxs
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetCachedSigningTxs(hash common.Hash) (interface{}, bool) {
|
||||
return c.signingTxsCache.Get(hash)
|
||||
func (x *XDPoS) GetCachedSigningTxs(hash common.Hash) (interface{}, bool) {
|
||||
return x.signingTxsCache.Get(hash)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,18 @@
|
|||
package XDPoS
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
func TestNewAdaptorShallContainMultipleConsensusEngine(t *testing.T) {
|
||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAdaptorShouldShareDbWithV1Engine(t *testing.T) {
|
||||
database := rawdb.NewMemoryDatabase()
|
||||
config := params.TestXDPoSMockChainConfig.XDPoS
|
||||
engine := New(config, database)
|
||||
|
||||
assert := assert.New(t)
|
||||
assert.Equal(engine.EngineV1.GetDb(), engine.GetDb())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,62 +15,19 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/accounts"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// SignerFn is a signer callback function to request a hash to be signed by a
|
||||
// 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
|
||||
// signing. It is the hash of the entire header apart from the 65 byte signature
|
||||
// contained at the end of the extra data.
|
||||
//
|
||||
// Note, the method requires the extra data to be at least 65 bytes, otherwise it
|
||||
// panics. This is done to avoid accidentally using both forms (signature present
|
||||
// or not), which could be abused to produce different hashes for the same header.
|
||||
func sigHash(header *types.Header) (hash common.Hash) {
|
||||
hasher := sha3.NewKeccak256()
|
||||
|
||||
err := rlp.Encode(hasher, []interface{}{
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
header.Root,
|
||||
header.TxHash,
|
||||
header.ReceiptHash,
|
||||
header.Bloom,
|
||||
header.Difficulty,
|
||||
header.Number,
|
||||
header.GasLimit,
|
||||
header.GasUsed,
|
||||
header.Time,
|
||||
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Fail to encode", err)
|
||||
}
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
|
||||
func SigHash(header *types.Header) (hash common.Hash) {
|
||||
return sigHash(header)
|
||||
}
|
||||
|
||||
// ecrecover extracts the Ethereum account address from a signed header.
|
||||
func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
|
||||
// If the signature's already cached, return that
|
||||
|
|
@ -85,7 +42,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er
|
|||
signature := header.Extra[len(header.Extra)-utils.ExtraSeal:]
|
||||
|
||||
// Recover the public key and the Ethereum address
|
||||
pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature)
|
||||
pubkey, err := crypto.Ecrecover(utils.SigHash(header).Bytes(), signature)
|
||||
if err != nil {
|
||||
return common.Address{}, err
|
||||
}
|
||||
|
|
@ -148,25 +105,25 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v1 {
|
|||
|
||||
// Author implements consensus.Engine, returning the Ethereum address recovered
|
||||
// from the signature in the header's extra-data section.
|
||||
func (c *XDPoS_v1) Author(header *types.Header) (common.Address, error) {
|
||||
return ecrecover(header, c.signatures)
|
||||
func (x *XDPoS_v1) Author(header *types.Header) (common.Address, error) {
|
||||
return ecrecover(header, x.signatures)
|
||||
}
|
||||
|
||||
// VerifyHeader checks whether a header conforms to the consensus rules.
|
||||
func (c *XDPoS_v1) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||
return c.verifyHeaderWithCache(chain, header, nil, fullVerify)
|
||||
func (x *XDPoS_v1) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||
return x.verifyHeaderWithCache(chain, header, nil, fullVerify)
|
||||
}
|
||||
|
||||
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
|
||||
// method returns a quit channel to abort the operations and a results channel to
|
||||
// retrieve the async verifications (the order is that of the input slice).
|
||||
func (c *XDPoS_v1) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
|
||||
func (x *XDPoS_v1) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
|
||||
abort := make(chan struct{})
|
||||
results := make(chan error, len(headers))
|
||||
|
||||
go func() {
|
||||
for i, header := range headers {
|
||||
err := c.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i])
|
||||
err := x.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i])
|
||||
|
||||
select {
|
||||
case <-abort:
|
||||
|
|
@ -178,14 +135,14 @@ func (c *XDPoS_v1) VerifyHeaders(chain consensus.ChainReader, headers []*types.H
|
|||
return abort, results
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
_, check := c.verifiedHeaders.Get(header.Hash())
|
||||
func (x *XDPoS_v1) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
_, check := x.verifiedHeaders.Get(header.Hash())
|
||||
if check {
|
||||
return nil
|
||||
}
|
||||
err := c.verifyHeader(chain, header, parents, fullVerify)
|
||||
err := x.verifyHeader(chain, header, parents, fullVerify)
|
||||
if err == nil {
|
||||
c.verifiedHeaders.Add(header.Hash(), true)
|
||||
x.verifiedHeaders.Add(header.Hash(), true)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -194,9 +151,9 @@ func (c *XDPoS_v1) verifyHeaderWithCache(chain consensus.ChainReader, header *ty
|
|||
// caller may optionally pass in a batch of parents (ascending order) to avoid
|
||||
// looking those up from the database. This is useful for concurrently verifying
|
||||
// a batch of new headers.
|
||||
func (c *XDPoS_v1) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
func (x *XDPoS_v1) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
// If we're running a engine faking, accept any block as valid
|
||||
if c.config.SkipValidation {
|
||||
if x.config.SkipValidation {
|
||||
return nil
|
||||
}
|
||||
if common.IsTestnet {
|
||||
|
|
@ -207,7 +164,7 @@ func (c *XDPoS_v1) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
}
|
||||
number := header.Number.Uint64()
|
||||
if fullVerify {
|
||||
if header.Number.Uint64() > c.config.Epoch && len(header.Validator) == 0 {
|
||||
if header.Number.Uint64() > x.config.Epoch && len(header.Validator) == 0 {
|
||||
return consensus.ErrNoValidatorSignature
|
||||
}
|
||||
// Don't waste time checking blocks from the future
|
||||
|
|
@ -216,7 +173,7 @@ func (c *XDPoS_v1) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
}
|
||||
}
|
||||
// Checkpoint blocks need to enforce zero beneficiary
|
||||
checkpoint := (number % c.config.Epoch) == 0
|
||||
checkpoint := (number % x.config.Epoch) == 0
|
||||
if checkpoint && header.Coinbase != (common.Address{}) {
|
||||
return utils.ErrInvalidCheckpointBeneficiary
|
||||
}
|
||||
|
|
@ -256,14 +213,14 @@ func (c *XDPoS_v1) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
return err
|
||||
}
|
||||
// All basic checks passed, verify cascading fields
|
||||
return c.verifyCascadingFields(chain, header, parents, fullVerify)
|
||||
return x.verifyCascadingFields(chain, header, parents, fullVerify)
|
||||
}
|
||||
|
||||
// verifyCascadingFields verifies all the header fields that are not standalone,
|
||||
// rather depend on a batch of previous headers. The caller may optionally pass
|
||||
// in a batch of parents (ascending order) to avoid looking those up from the
|
||||
// database. This is useful for concurrently verifying a batch of new headers.
|
||||
func (c *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
func (x *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
// The genesis block is the always valid dead-end
|
||||
number := header.Number.Uint64()
|
||||
if number == 0 {
|
||||
|
|
@ -279,12 +236,12 @@ func (c *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *ty
|
|||
if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
|
||||
return consensus.ErrUnknownAncestor
|
||||
}
|
||||
if parent.Time.Uint64()+c.config.Period > header.Time.Uint64() {
|
||||
if parent.Time.Uint64()+x.config.Period > header.Time.Uint64() {
|
||||
return utils.ErrInvalidTimestamp
|
||||
}
|
||||
|
||||
if number%c.config.Epoch != 0 {
|
||||
return c.verifySeal(chain, header, parents, fullVerify)
|
||||
if number%x.config.Epoch != 0 {
|
||||
return x.verifySeal(chain, header, parents, fullVerify)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -292,42 +249,42 @@ func (c *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *ty
|
|||
when it happens we get the signers list by requesting smart contract
|
||||
*/
|
||||
// Retrieve the snapshot needed to verify this header and cache it
|
||||
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
|
||||
snap, err := x.snapshot(chain, number-1, header.ParentHash, parents)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
signers := snap.GetSigners()
|
||||
err = c.checkSignersOnCheckpoint(chain, header, signers)
|
||||
err = x.checkSignersOnCheckpoint(chain, header, signers)
|
||||
if err == nil {
|
||||
return c.verifySeal(chain, header, parents, fullVerify)
|
||||
return x.verifySeal(chain, header, parents, fullVerify)
|
||||
}
|
||||
|
||||
signers, err = c.getSignersFromContract(chain, header)
|
||||
signers, err = x.getSignersFromContract(chain, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.checkSignersOnCheckpoint(chain, header, signers)
|
||||
err = x.checkSignersOnCheckpoint(chain, header, signers)
|
||||
if err == nil {
|
||||
return c.verifySeal(chain, header, parents, fullVerify)
|
||||
return x.verifySeal(chain, header, parents, fullVerify)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header *types.Header, signers []common.Address) error {
|
||||
func (x *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header *types.Header, signers []common.Address) error {
|
||||
number := header.Number.Uint64()
|
||||
// ignore signerCheck at checkpoint block 14458500 due to wrong snapshot at gap 14458495
|
||||
if number == common.IgnoreSignerCheckBlock {
|
||||
return nil
|
||||
}
|
||||
penPenalties := []common.Address{}
|
||||
if c.HookPenalty != nil || c.HookPenaltyTIPSigning != nil {
|
||||
if x.HookPenalty != nil || x.HookPenaltyTIPSigning != nil {
|
||||
var err error
|
||||
if chain.Config().IsTIPSigning(header.Number) {
|
||||
penPenalties, err = c.HookPenaltyTIPSigning(chain, header, signers)
|
||||
penPenalties, err = x.HookPenaltyTIPSigning(chain, header, signers)
|
||||
} else {
|
||||
penPenalties, err = c.HookPenalty(chain, number)
|
||||
penPenalties, err = x.HookPenalty(chain, number)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -342,8 +299,8 @@ func (c *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header
|
|||
}
|
||||
signers = common.RemoveItemFromArray(signers, penPenalties)
|
||||
for i := 1; i <= common.LimitPenaltyEpoch; i++ {
|
||||
if number > uint64(i)*c.config.Epoch {
|
||||
signers = removePenaltiesFromBlock(chain, signers, number-uint64(i)*c.config.Epoch)
|
||||
if number > uint64(i)*x.config.Epoch {
|
||||
signers = removePenaltiesFromBlock(chain, signers, number-uint64(i)*x.config.Epoch)
|
||||
}
|
||||
}
|
||||
extraSuffix := len(header.Extra) - utils.ExtraSeal
|
||||
|
|
@ -354,8 +311,8 @@ func (c *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header
|
|||
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 utils.ErrInvalidCheckpointSigners
|
||||
}
|
||||
if c.HookVerifyMNs != nil {
|
||||
err := c.HookVerifyMNs(header, signers)
|
||||
if x.HookVerifyMNs != nil {
|
||||
err := x.HookVerifyMNs(header, signers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -364,8 +321,8 @@ func (c *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) IsAuthorisedAddress(header *types.Header, chain consensus.ChainReader, address common.Address) bool {
|
||||
snap, err := c.GetSnapshot(chain, header)
|
||||
func (x *XDPoS_v1) IsAuthorisedAddress(header *types.Header, chain consensus.ChainReader, address common.Address) bool {
|
||||
snap, err := x.GetSnapshot(chain, header)
|
||||
if err != nil {
|
||||
log.Error("[IsAuthorisedAddress] Can't get snapshot with at ", "number", header.Number, "hash", header.Hash().Hex(), "err", err)
|
||||
return false
|
||||
|
|
@ -376,26 +333,26 @@ func (c *XDPoS_v1) IsAuthorisedAddress(header *types.Header, chain consensus.Cha
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*SnapshotV1, error) {
|
||||
func (x *XDPoS_v1) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*SnapshotV1, error) {
|
||||
number := header.Number.Uint64()
|
||||
log.Trace("get snapshot", "number", number, "hash", header.Hash())
|
||||
snap, err := c.snapshot(chain, number, header.Hash(), nil)
|
||||
snap, err := x.snapshot(chain, number, header.Hash(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snap, nil
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, header *types.Header) ([]common.Address, error) {
|
||||
snap, err := c.GetSnapshot(chain, header)
|
||||
func (x *XDPoS_v1) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, header *types.Header) ([]common.Address, error) {
|
||||
snap, err := x.GetSnapshot(chain, header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snap.GetSigners(), nil
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) StoreSnapshot(snap *SnapshotV1) error {
|
||||
return snap.store(c.db)
|
||||
func (x *XDPoS_v1) StoreSnapshot(snap *SnapshotV1) error {
|
||||
return snap.store(x.db)
|
||||
}
|
||||
|
||||
func position(list []common.Address, x common.Address) int {
|
||||
|
|
@ -407,21 +364,21 @@ func position(list []common.Address, x common.Address) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address {
|
||||
func (x *XDPoS_v1) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address {
|
||||
n := header.Number.Uint64()
|
||||
e := c.config.Epoch
|
||||
e := x.config.Epoch
|
||||
switch {
|
||||
case n%e == 0:
|
||||
return c.GetMasternodesFromCheckpointHeader(header, n, e)
|
||||
return x.GetMasternodesFromCheckpointHeader(header, n, e)
|
||||
case n%e != 0:
|
||||
h := chain.GetHeaderByNumber(n - (n % e))
|
||||
return c.GetMasternodesFromCheckpointHeader(h, n, e)
|
||||
return x.GetMasternodesFromCheckpointHeader(h, n, e)
|
||||
default:
|
||||
return []common.Address{}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) GetPeriod() uint64 { return c.config.Period }
|
||||
func (x *XDPoS_v1) GetPeriod() uint64 { return x.config.Period }
|
||||
|
||||
func whoIsCreator(snap *SnapshotV1, header *types.Header) (common.Address, error) {
|
||||
if header.Number.Uint64() == 0 {
|
||||
|
|
@ -434,8 +391,8 @@ func whoIsCreator(snap *SnapshotV1, header *types.Header) (common.Address, error
|
|||
return m, nil
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (int, int, int, bool, error) {
|
||||
masternodes := c.GetMasternodes(chain, parent)
|
||||
func (x *XDPoS_v1) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (int, int, int, bool, error) {
|
||||
masternodes := x.GetMasternodes(chain, parent)
|
||||
|
||||
// if common.IsTestnet {
|
||||
// // Only three mns hard code for XDC testnet.
|
||||
|
|
@ -446,7 +403,7 @@ func (c *XDPoS_v1) YourTurn(chain consensus.ChainReader, parent *types.Header, s
|
|||
// }
|
||||
// }
|
||||
|
||||
snap, err := c.GetSnapshot(chain, parent)
|
||||
snap, err := x.GetSnapshot(chain, parent)
|
||||
if err != nil {
|
||||
log.Warn("Failed when trying to commit new work", "err", err)
|
||||
return 0, -1, -1, false, err
|
||||
|
|
@ -465,7 +422,7 @@ func (c *XDPoS_v1) YourTurn(chain consensus.ChainReader, parent *types.Header, s
|
|||
preIndex = position(masternodes, pre)
|
||||
}
|
||||
curIndex := position(masternodes, signer)
|
||||
if signer == c.signer {
|
||||
if signer == x.signer {
|
||||
log.Debug("Masternodes cycle info", "number of masternodes", len(masternodes), "previous", pre, "position", preIndex, "current", signer, "position", curIndex)
|
||||
}
|
||||
for i, s := range masternodes {
|
||||
|
|
@ -478,7 +435,7 @@ func (c *XDPoS_v1) YourTurn(chain consensus.ChainReader, parent *types.Header, s
|
|||
}
|
||||
|
||||
// snapshot retrieves the authorization snapshot at a given point in time.
|
||||
func (c *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) (*SnapshotV1, error) {
|
||||
func (x *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) (*SnapshotV1, error) {
|
||||
// Search for a SnapshotV1 in memory or on disk for checkpoints
|
||||
var (
|
||||
headers []*types.Header
|
||||
|
|
@ -486,14 +443,14 @@ func (c *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash com
|
|||
)
|
||||
for snap == nil {
|
||||
// If an in-memory SnapshotV1 was found, use that
|
||||
if s, ok := c.recents.Get(hash); ok {
|
||||
if s, ok := x.recents.Get(hash); ok {
|
||||
snap = s.(*SnapshotV1)
|
||||
break
|
||||
}
|
||||
// If an on-disk checkpoint snapshot can be found, use that
|
||||
// checkpoint snapshot = checkpoint - gap
|
||||
if (number+c.config.Gap)%c.config.Epoch == 0 {
|
||||
if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil {
|
||||
if (number+x.config.Gap)%x.config.Epoch == 0 {
|
||||
if s, err := loadSnapshot(x.config, x.signatures, x.db, hash); err == nil {
|
||||
log.Trace("Loaded voting snapshot form disk", "number", number, "hash", hash)
|
||||
snap = s
|
||||
break
|
||||
|
|
@ -502,15 +459,15 @@ func (c *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash com
|
|||
// If we're at block zero, make a snapshot
|
||||
if number == 0 {
|
||||
genesis := chain.GetHeaderByNumber(0)
|
||||
if err := c.VerifyHeader(chain, genesis, true); err != nil {
|
||||
if err := x.VerifyHeader(chain, genesis, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signers := make([]common.Address, (len(genesis.Extra)-utils.ExtraVanity-utils.ExtraSeal)/common.AddressLength)
|
||||
for i := 0; i < len(signers); i++ {
|
||||
copy(signers[i][:], genesis.Extra[utils.ExtraVanity+i*common.AddressLength:])
|
||||
}
|
||||
snap = newSnapshot(c.config, c.signatures, 0, genesis.Hash(), signers)
|
||||
if err := snap.store(c.db); err != nil {
|
||||
snap = newSnapshot(x.config, x.signatures, 0, genesis.Hash(), signers)
|
||||
if err := snap.store(x.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Trace("Stored genesis voting snapshot to disk")
|
||||
|
|
@ -543,11 +500,11 @@ func (c *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash com
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.recents.Add(snap.Hash, snap)
|
||||
x.recents.Add(snap.Hash, snap)
|
||||
|
||||
// If we've generated a new checkpoint snapshot, save to disk
|
||||
if (snap.Number+c.config.Gap)%c.config.Epoch == 0 {
|
||||
if err = snap.store(c.db); err != nil {
|
||||
if (snap.Number+x.config.Gap)%x.config.Epoch == 0 {
|
||||
if err = snap.store(x.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash)
|
||||
|
|
@ -557,7 +514,7 @@ func (c *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash com
|
|||
|
||||
// VerifyUncles implements consensus.Engine, always returning an error for any
|
||||
// uncles as this consensus mechanism doesn't permit uncles.
|
||||
func (c *XDPoS_v1) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
||||
func (x *XDPoS_v1) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
||||
if len(block.Uncles()) > 0 {
|
||||
return errors.New("uncles not allowed")
|
||||
}
|
||||
|
|
@ -566,8 +523,8 @@ func (c *XDPoS_v1) VerifyUncles(chain consensus.ChainReader, block *types.Block)
|
|||
|
||||
// VerifySeal implements consensus.Engine, checking whether the signature contained
|
||||
// in the header satisfies the consensus protocol requirements.
|
||||
func (c *XDPoS_v1) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
|
||||
return c.verifySeal(chain, header, nil, true)
|
||||
func (x *XDPoS_v1) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
|
||||
return x.verifySeal(chain, header, nil, true)
|
||||
}
|
||||
|
||||
// verifySeal checks whether the signature contained in the header satisfies the
|
||||
|
|
@ -576,20 +533,20 @@ func (c *XDPoS_v1) VerifySeal(chain consensus.ChainReader, header *types.Header)
|
|||
// from.
|
||||
// verifySeal also checks the pair of creator-validator set in the header satisfies
|
||||
// the double validation.
|
||||
func (c *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
func (x *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
// Verifying the genesis block is not supported
|
||||
number := header.Number.Uint64()
|
||||
if number == 0 {
|
||||
return utils.ErrUnknownBlock
|
||||
}
|
||||
// Retrieve the snapshot needed to verify this header and cache it
|
||||
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
|
||||
snap, err := x.snapshot(chain, number-1, header.ParentHash, parents)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resolve the authorization key and check against signers
|
||||
creator, err := ecrecover(header, c.signatures)
|
||||
creator, err := ecrecover(header, x.signatures)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -599,7 +556,7 @@ func (c *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header,
|
|||
} else {
|
||||
parent = chain.GetHeader(header.ParentHash, number-1)
|
||||
}
|
||||
difficulty := c.calcDifficulty(chain, parent, creator)
|
||||
difficulty := x.calcDifficulty(chain, parent, creator)
|
||||
log.Debug("verify seal block", "number", header.Number, "hash", header.Hash(), "block difficulty", header.Difficulty, "calc difficulty", difficulty, "creator", creator)
|
||||
// Ensure that the block's difficulty is meaningful (may not be correct at this point)
|
||||
if number > 0 {
|
||||
|
|
@ -607,7 +564,7 @@ func (c *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header,
|
|||
return utils.ErrInvalidDifficulty
|
||||
}
|
||||
}
|
||||
masternodes := c.GetMasternodes(chain, header)
|
||||
masternodes := x.GetMasternodes(chain, header)
|
||||
mstring := []string{}
|
||||
for _, m := range masternodes {
|
||||
mstring = append(mstring, m.String())
|
||||
|
|
@ -636,7 +593,7 @@ func (c *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header,
|
|||
// There is only case that we don't allow signer to create two continuous blocks.
|
||||
if limit := uint64(2); seen > number-limit {
|
||||
// Only take into account the non-epoch blocks
|
||||
if number%c.config.Epoch != 0 {
|
||||
if number%x.config.Epoch != 0 {
|
||||
return utils.ErrUnauthorized
|
||||
}
|
||||
}
|
||||
|
|
@ -646,14 +603,14 @@ func (c *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header,
|
|||
|
||||
// header must contain validator info following double validation design
|
||||
// start checking from epoch 2nd.
|
||||
if header.Number.Uint64() > c.config.Epoch && fullVerify {
|
||||
validator, err := c.RecoverValidator(header)
|
||||
if header.Number.Uint64() > x.config.Epoch && fullVerify {
|
||||
validator, err := x.RecoverValidator(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// verify validator
|
||||
assignedValidator, err := c.GetValidator(creator, chain, header)
|
||||
assignedValidator, err := x.GetValidator(creator, chain, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -665,8 +622,8 @@ func (c *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) GetValidator(creator common.Address, chain consensus.ChainReader, header *types.Header) (common.Address, error) {
|
||||
epoch := c.config.Epoch
|
||||
func (x *XDPoS_v1) GetValidator(creator common.Address, chain consensus.ChainReader, header *types.Header) (common.Address, error) {
|
||||
epoch := x.config.Epoch
|
||||
no := header.Number.Uint64()
|
||||
cpNo := no
|
||||
if no%epoch != 0 {
|
||||
|
|
@ -692,23 +649,23 @@ func (c *XDPoS_v1) GetValidator(creator common.Address, chain consensus.ChainRea
|
|||
|
||||
// Prepare implements consensus.Engine, preparing all the consensus fields of the
|
||||
// header for running the transactions on top.
|
||||
func (c *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
||||
func (x *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
||||
// If the block isn't a checkpoint, cast a random vote (good enough for now)
|
||||
header.Coinbase = common.Address{}
|
||||
header.Nonce = types.BlockNonce{}
|
||||
|
||||
number := header.Number.Uint64()
|
||||
// Assemble the voting snapshot to check which votes make sense
|
||||
snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
|
||||
snap, err := x.snapshot(chain, number-1, header.ParentHash, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if number%c.config.Epoch != 0 {
|
||||
c.lock.RLock()
|
||||
if number%x.config.Epoch != 0 {
|
||||
x.lock.RLock()
|
||||
|
||||
// Gather all the proposals that make sense voting on
|
||||
addresses := make([]common.Address, 0, len(c.proposals))
|
||||
for address, authorize := range c.proposals {
|
||||
addresses := make([]common.Address, 0, len(x.proposals))
|
||||
for address, authorize := range x.proposals {
|
||||
if snap.validVote(address, authorize) {
|
||||
addresses = append(addresses, address)
|
||||
}
|
||||
|
|
@ -716,20 +673,20 @@ func (c *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) er
|
|||
// If there's pending proposals, cast a vote on them
|
||||
if len(addresses) > 0 {
|
||||
header.Coinbase = addresses[rand.Intn(len(addresses))]
|
||||
if c.proposals[header.Coinbase] {
|
||||
if x.proposals[header.Coinbase] {
|
||||
copy(header.Nonce[:], utils.NonceAuthVote)
|
||||
} else {
|
||||
copy(header.Nonce[:], utils.NonceDropVote)
|
||||
}
|
||||
}
|
||||
c.lock.RUnlock()
|
||||
x.lock.RUnlock()
|
||||
}
|
||||
parent := chain.GetHeader(header.ParentHash, number-1)
|
||||
if parent == nil {
|
||||
return consensus.ErrUnknownAncestor
|
||||
}
|
||||
// Set the correct difficulty
|
||||
header.Difficulty = c.calcDifficulty(chain, parent, c.signer)
|
||||
header.Difficulty = x.calcDifficulty(chain, parent, x.signer)
|
||||
log.Debug("CalcDifficulty ", "number", header.Number, "difficulty", header.Difficulty)
|
||||
// Ensure the extra data has all it's components
|
||||
if len(header.Extra) < utils.ExtraVanity {
|
||||
|
|
@ -737,14 +694,14 @@ func (c *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) er
|
|||
}
|
||||
header.Extra = header.Extra[:utils.ExtraVanity]
|
||||
masternodes := snap.GetSigners()
|
||||
if number >= c.config.Epoch && number%c.config.Epoch == 0 {
|
||||
if c.HookPenalty != nil || c.HookPenaltyTIPSigning != nil {
|
||||
if number >= x.config.Epoch && number%x.config.Epoch == 0 {
|
||||
if x.HookPenalty != nil || x.HookPenaltyTIPSigning != nil {
|
||||
var penMasternodes []common.Address
|
||||
var err error
|
||||
if chain.Config().IsTIPSigning(header.Number) {
|
||||
penMasternodes, err = c.HookPenaltyTIPSigning(chain, header, masternodes)
|
||||
penMasternodes, err = x.HookPenaltyTIPSigning(chain, header, masternodes)
|
||||
} else {
|
||||
penMasternodes, err = c.HookPenalty(chain, number)
|
||||
penMasternodes, err = x.HookPenalty(chain, number)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -760,15 +717,15 @@ func (c *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) er
|
|||
}
|
||||
// Prevent penalized masternode(s) within 4 recent epochs
|
||||
for i := 1; i <= common.LimitPenaltyEpoch; i++ {
|
||||
if number > uint64(i)*c.config.Epoch {
|
||||
masternodes = removePenaltiesFromBlock(chain, masternodes, number-uint64(i)*c.config.Epoch)
|
||||
if number > uint64(i)*x.config.Epoch {
|
||||
masternodes = removePenaltiesFromBlock(chain, masternodes, number-uint64(i)*x.config.Epoch)
|
||||
}
|
||||
}
|
||||
for _, masternode := range masternodes {
|
||||
header.Extra = append(header.Extra, masternode[:]...)
|
||||
}
|
||||
if c.HookValidator != nil {
|
||||
validators, err := c.HookValidator(header, masternodes)
|
||||
if x.HookValidator != nil {
|
||||
validators, err := x.HookValidator(header, masternodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -782,18 +739,18 @@ func (c *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) er
|
|||
|
||||
// Ensure the timestamp has the correct delay
|
||||
|
||||
header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(c.config.Period))
|
||||
header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(x.config.Period))
|
||||
if header.Time.Int64() < time.Now().Unix() {
|
||||
header.Time = big.NewInt(time.Now().Unix())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []utils.Masternode) error {
|
||||
func (x *XDPoS_v1) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []utils.Masternode) error {
|
||||
number := header.Number.Uint64()
|
||||
log.Trace("take snapshot", "number", number, "hash", header.Hash())
|
||||
// get snapshot
|
||||
snap, err := c.snapshot(chain, number, header.Hash(), nil)
|
||||
snap, err := x.snapshot(chain, number, header.Hash(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -806,22 +763,22 @@ func (c *XDPoS_v1) UpdateMasternodes(chain consensus.ChainReader, header *types.
|
|||
for _, n := range ms {
|
||||
nm = append(nm, n.Address.String())
|
||||
}
|
||||
c.recents.Add(snap.Hash, snap)
|
||||
x.recents.Add(snap.Hash, snap)
|
||||
log.Info("New set of masternodes has been updated to snapshot", "number", snap.Number, "hash", snap.Hash, "new masternodes", nm)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||
// rewards given, and returns the final block.
|
||||
func (c *XDPoS_v1) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||
func (x *XDPoS_v1) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||
// set block reward
|
||||
number := header.Number.Uint64()
|
||||
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
||||
|
||||
// _ = c.CacheData(header, txs, receipts)
|
||||
|
||||
if c.HookReward != nil && number%rCheckpoint == 0 {
|
||||
err, rewards := c.HookReward(chain, state, parentState, header)
|
||||
if x.HookReward != nil && number%rCheckpoint == 0 {
|
||||
err, rewards := x.HookReward(chain, state, parentState, header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -846,17 +803,17 @@ func (c *XDPoS_v1) Finalize(chain consensus.ChainReader, header *types.Header, s
|
|||
|
||||
// Authorize injects a private key into the consensus engine to mint new blocks
|
||||
// with.
|
||||
func (c *XDPoS_v1) Authorize(signer common.Address, signFn clique.SignerFn) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
func (x *XDPoS_v1) Authorize(signer common.Address, signFn clique.SignerFn) {
|
||||
x.lock.Lock()
|
||||
defer x.lock.Unlock()
|
||||
|
||||
c.signer = signer
|
||||
c.signFn = signFn
|
||||
x.signer = signer
|
||||
x.signFn = signFn
|
||||
}
|
||||
|
||||
// Seal implements consensus.Engine, attempting to create a sealed block using
|
||||
// the local signing credentials.
|
||||
func (c *XDPoS_v1) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
|
||||
func (x *XDPoS_v1) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
|
||||
header := block.Header()
|
||||
|
||||
// Sealing the genesis block is not supported
|
||||
|
|
@ -866,20 +823,20 @@ func (c *XDPoS_v1) Seal(chain consensus.ChainReader, block *types.Block, stop <-
|
|||
}
|
||||
// For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing)
|
||||
// checkpoint blocks have no tx
|
||||
if c.config.Period == 0 && len(block.Transactions()) == 0 && number%c.config.Epoch != 0 {
|
||||
if x.config.Period == 0 && len(block.Transactions()) == 0 && number%x.config.Epoch != 0 {
|
||||
return nil, utils.ErrWaitTransactions
|
||||
}
|
||||
// Don't hold the signer fields for the entire sealing procedure
|
||||
c.lock.RLock()
|
||||
signer, signFn := c.signer, c.signFn
|
||||
c.lock.RUnlock()
|
||||
x.lock.RLock()
|
||||
signer, signFn := x.signer, x.signFn
|
||||
x.lock.RUnlock()
|
||||
|
||||
// Bail out if we're unauthorized to sign a block
|
||||
snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
|
||||
snap, err := x.snapshot(chain, number-1, header.ParentHash, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
masternodes := c.GetMasternodes(chain, header)
|
||||
masternodes := x.GetMasternodes(chain, header)
|
||||
if _, authorized := snap.Signers[signer]; !authorized {
|
||||
valid := false
|
||||
for _, m := range masternodes {
|
||||
|
|
@ -901,7 +858,7 @@ func (c *XDPoS_v1) Seal(chain consensus.ChainReader, block *types.Block, stop <-
|
|||
// There is only case that we don't allow signer to create two continuous blocks.
|
||||
if limit := uint64(2); number < limit || seen > number-limit {
|
||||
// Only take into account the non-epoch blocks
|
||||
if number%c.config.Epoch != 0 {
|
||||
if number%x.config.Epoch != 0 {
|
||||
log.Info("Signed recently, must wait for others ", "len(masternodes)", len(masternodes), "number", number, "limit", limit, "seen", seen, "recent", recent.String(), "snap.Recents", snap.Recents)
|
||||
<-stop
|
||||
return nil, nil
|
||||
|
|
@ -916,12 +873,12 @@ func (c *XDPoS_v1) Seal(chain consensus.ChainReader, block *types.Block, stop <-
|
|||
default:
|
||||
}
|
||||
// Sign all the things!
|
||||
sighash, err := signFn(accounts.Account{Address: signer}, sigHash(header).Bytes())
|
||||
sighash, err := signFn(accounts.Account{Address: signer}, utils.SigHash(header).Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(header.Extra[len(header.Extra)-utils.ExtraSeal:], sighash)
|
||||
m2, err := c.GetValidator(signer, chain, header)
|
||||
m2, err := x.GetValidator(signer, chain, header)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't get block validator: %v", err)
|
||||
}
|
||||
|
|
@ -934,30 +891,30 @@ func (c *XDPoS_v1) Seal(chain consensus.ChainReader, block *types.Block, stop <-
|
|||
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
||||
// that a new block should have based on the previous blocks in the chain and the
|
||||
// current signer.
|
||||
func (c *XDPoS_v1) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
|
||||
return c.calcDifficulty(chain, parent, c.signer)
|
||||
func (x *XDPoS_v1) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
|
||||
return x.calcDifficulty(chain, parent, x.signer)
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) calcDifficulty(chain consensus.ChainReader, parent *types.Header, signer common.Address) *big.Int {
|
||||
func (x *XDPoS_v1) calcDifficulty(chain consensus.ChainReader, parent *types.Header, signer common.Address) *big.Int {
|
||||
// If we're running a engine faking, skip calculation
|
||||
if c.config.SkipValidation {
|
||||
if x.config.SkipValidation {
|
||||
return big.NewInt(1)
|
||||
}
|
||||
len, preIndex, curIndex, _, err := c.YourTurn(chain, parent, signer)
|
||||
len, preIndex, curIndex, _, err := x.YourTurn(chain, parent, signer)
|
||||
if err != nil {
|
||||
return big.NewInt(int64(len + curIndex - preIndex))
|
||||
}
|
||||
return big.NewInt(int64(len - utils.Hop(len, preIndex, curIndex)))
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) RecoverSigner(header *types.Header) (common.Address, error) {
|
||||
return ecrecover(header, c.signatures)
|
||||
func (x *XDPoS_v1) RecoverSigner(header *types.Header) (common.Address, error) {
|
||||
return ecrecover(header, x.signatures)
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) RecoverValidator(header *types.Header) (common.Address, error) {
|
||||
func (x *XDPoS_v1) RecoverValidator(header *types.Header) (common.Address, error) {
|
||||
// If the signature's already cached, return that
|
||||
hash := header.Hash()
|
||||
if address, known := c.validatorSignatures.Get(hash); known {
|
||||
if address, known := x.validatorSignatures.Get(hash); known {
|
||||
return address.(common.Address), nil
|
||||
}
|
||||
// Retrieve the signature from the header.Validator
|
||||
|
|
@ -966,19 +923,19 @@ func (c *XDPoS_v1) RecoverValidator(header *types.Header) (common.Address, error
|
|||
return common.Address{}, consensus.ErrFailValidatorSignature
|
||||
}
|
||||
// Recover the public key and the Ethereum address
|
||||
pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), header.Validator)
|
||||
pubkey, err := crypto.Ecrecover(utils.SigHash(header).Bytes(), header.Validator)
|
||||
if err != nil {
|
||||
return common.Address{}, err
|
||||
}
|
||||
var signer common.Address
|
||||
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
|
||||
|
||||
c.validatorSignatures.Add(hash, signer)
|
||||
x.validatorSignatures.Add(hash, signer)
|
||||
return signer, nil
|
||||
}
|
||||
|
||||
// Get master nodes over extra data of previous checkpoint block.
|
||||
func (c *XDPoS_v1) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Header, n, e uint64) []common.Address {
|
||||
func (x *XDPoS_v1) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Header, n, e uint64) []common.Address {
|
||||
if preCheckpointHeader == nil {
|
||||
log.Info("Previous checkpoint's header is empty", "block number", n, "epoch", e)
|
||||
return []common.Address{}
|
||||
|
|
@ -991,8 +948,8 @@ func (c *XDPoS_v1) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types
|
|||
return masternodes
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) GetDb() ethdb.Database {
|
||||
return c.db
|
||||
func (x *XDPoS_v1) GetDb() ethdb.Database {
|
||||
return x.db
|
||||
}
|
||||
|
||||
// Extract validators from byte array.
|
||||
|
|
@ -1034,23 +991,23 @@ func GetM1M2FromCheckpointHeader(checkpointHeader *types.Header, currentHeader *
|
|||
return m1m2, nil
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) getSignersFromContract(chain consensus.ChainReader, checkpointHeader *types.Header) ([]common.Address, error) {
|
||||
func (x *XDPoS_v1) getSignersFromContract(chain consensus.ChainReader, checkpointHeader *types.Header) ([]common.Address, error) {
|
||||
startGapBlockHeader := checkpointHeader
|
||||
number := checkpointHeader.Number.Uint64()
|
||||
for step := uint64(1); step <= chain.Config().XDPoS.Gap; step++ {
|
||||
startGapBlockHeader = chain.GetHeader(startGapBlockHeader.ParentHash, number-step)
|
||||
}
|
||||
signers, err := c.HookGetSignersFromContract(startGapBlockHeader.Hash())
|
||||
signers, err := x.HookGetSignersFromContract(startGapBlockHeader.Hash())
|
||||
if err != nil {
|
||||
return []common.Address{}, fmt.Errorf("Can't get signers from Smart Contract . Err: %v", err)
|
||||
}
|
||||
return signers, nil
|
||||
}
|
||||
|
||||
func NewFaker(db ethdb.Database) *XDPoS_v1 {
|
||||
func NewFaker(db ethdb.Database, config *params.XDPoSConfig) *XDPoS_v1 {
|
||||
var fakeEngine *XDPoS_v1
|
||||
// Set any missing consensus parameters to their defaults
|
||||
conf := params.TestXDPoSMockChainConfig.XDPoS
|
||||
conf := config
|
||||
|
||||
// Allocate the snapshot caches and create the engine
|
||||
recents, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||
|
|
|
|||
|
|
@ -1 +1,42 @@
|
|||
package engine_v2
|
||||
|
||||
import (
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
type XDPoS_v2 struct {
|
||||
config *params.XDPoSConfig // Consensus engine configuration parameters
|
||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||
}
|
||||
|
||||
func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v2 {
|
||||
return &XDPoS_v2{
|
||||
config: config,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFaker(db ethdb.Database, config *params.XDPoSConfig) *XDPoS_v2 {
|
||||
var fakeEngine *XDPoS_v2
|
||||
// Set any missing consensus parameters to their defaults
|
||||
conf := config
|
||||
|
||||
// Allocate the snapshot caches and create the engine
|
||||
fakeEngine = &XDPoS_v2{
|
||||
config: conf,
|
||||
db: db,
|
||||
}
|
||||
return fakeEngine
|
||||
}
|
||||
|
||||
func (consensus *XDPoS_v2) Author(header *types.Header) (common.Address, error) {
|
||||
return common.Address{}, nil
|
||||
}
|
||||
|
||||
func (consensus *XDPoS_v2) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ import (
|
|||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
)
|
||||
|
||||
func Position(list []common.Address, x common.Address) int {
|
||||
|
|
@ -109,3 +111,41 @@ func CompareSignersLists(list1 []common.Address, list2 []common.Address) bool {
|
|||
})
|
||||
return reflect.DeepEqual(list1, list2)
|
||||
}
|
||||
|
||||
// SignerFn is a signer callback function to request a hash to be signed by a
|
||||
// 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
|
||||
// signing. It is the hash of the entire header apart from the 65 byte signature
|
||||
// contained at the end of the extra data.
|
||||
//
|
||||
// Note, the method requires the extra data to be at least 65 bytes, otherwise it
|
||||
// panics. This is done to avoid accidentally using both forms (signature present
|
||||
// or not), which could be abused to produce different hashes for the same header.
|
||||
func SigHash(header *types.Header) (hash common.Hash) {
|
||||
hasher := sha3.NewKeccak256()
|
||||
|
||||
err := rlp.Encode(hasher, []interface{}{
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
header.Root,
|
||||
header.TxHash,
|
||||
header.ReceiptHash,
|
||||
header.Bloom,
|
||||
header.Difficulty,
|
||||
header.Number,
|
||||
header.GasLimit,
|
||||
header.GasUsed,
|
||||
header.Time,
|
||||
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Fail to encode", err)
|
||||
}
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,12 +18,13 @@
|
|||
package consensus
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// ChainReader defines a small collection of methods needed to access the local
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -36,7 +37,7 @@ var (
|
|||
)
|
||||
|
||||
func TestBlockSigner(t *testing.T) {
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000)
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
transactOpts := bind.NewKeyedTransactor(key)
|
||||
|
||||
blockSignerAddress, blockSigner, err := DeployBlockSigner(transactOpts, contractBackend, big.NewInt(99))
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/contracts/chequebook/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -46,7 +47,7 @@ func newTestBackend() *backends.SimulatedBackend {
|
|||
addr0: {Balance: big.NewInt(1000000000)},
|
||||
addr1: {Balance: big.NewInt(1000000000)},
|
||||
addr2: {Balance: big.NewInt(1000000000)},
|
||||
}, 10000000)
|
||||
}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
}
|
||||
|
||||
func deploy(prvKey *ecdsa.PrivateKey, amount *big.Int, backend *backends.SimulatedBackend) (common.Address, error) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/contracts/ens/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -35,7 +36,7 @@ var (
|
|||
)
|
||||
|
||||
func TestENS(t *testing.T) {
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000)
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
transactOpts := bind.NewKeyedTransactor(key)
|
||||
|
||||
ensAddr, ens, err := DeployENS(transactOpts, contractBackend)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -40,7 +41,7 @@ var (
|
|||
)
|
||||
|
||||
func TestRandomize(t *testing.T) {
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(100000000000000)}}, 10000000)
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(100000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
transactOpts := bind.NewKeyedTransactor(key)
|
||||
transactOpts.GasLimit = 1000000
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -47,7 +48,7 @@ var (
|
|||
|
||||
func getCommonBackend() *backends.SimulatedBackend {
|
||||
genesis := core.GenesisAlloc{acc1Addr: {Balance: big.NewInt(1000000000000)}}
|
||||
backend := backends.NewXDCSimulatedBackend(genesis, 10000000)
|
||||
backend := backends.NewXDCSimulatedBackend(genesis, 10000000, params.TestXDPoSMockChainConfig)
|
||||
backend.Commit()
|
||||
|
||||
return backend
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -46,7 +47,7 @@ var (
|
|||
)
|
||||
|
||||
func TestValidator(t *testing.T) {
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000)
|
||||
contractBackend := backends.NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
transactOpts := bind.NewKeyedTransactor(key)
|
||||
|
||||
validatorCap := new(big.Int)
|
||||
|
|
@ -86,7 +87,7 @@ func TestRewardBalance(t *testing.T) {
|
|||
acc1Addr: {Balance: new(big.Int).SetUint64(10000000)},
|
||||
acc2Addr: {Balance: new(big.Int).SetUint64(10000000)},
|
||||
acc4Addr: {Balance: new(big.Int).SetUint64(10000000)},
|
||||
}, 42000000)
|
||||
}, 42000000, params.TestXDPoSMockChainConfig)
|
||||
acc1Opts := bind.NewKeyedTransactor(acc1Key)
|
||||
acc2Opts := bind.NewKeyedTransactor(acc2Key)
|
||||
accounts := []*bind.TransactOpts{acc1Opts, acc2Opts}
|
||||
|
|
|
|||
30631
coverage.txt
30631
coverage.txt
File diff suppressed because it is too large
Load diff
2
go.mod
2
go.mod
|
|
@ -51,7 +51,7 @@ require (
|
|||
github.com/rs/cors v1.6.0
|
||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570
|
||||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d
|
||||
golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59
|
||||
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -87,6 +87,7 @@ github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59j
|
|||
github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
|
||||
github.com/ethereum/go-ethereum v1.9.9 h1:jnoBvjH8aMH++iH14XmiJdAsnRcmZUM+B5fsnEZBVE0=
|
||||
github.com/ethereum/go-ethereum v1.9.9/go.mod h1:a9TqabFudpDu1nucId+k9S8R9whYaHnGBLKFouA5EAo=
|
||||
github.com/ethereum/go-ethereum v1.10.10 h1:Ft2GcLQrr2M89l49g9NoqgNtJZ9AahzMb7N6VXKZy5U=
|
||||
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.6.0 h1:66qjqZk8kalYAvDRtM1AdAJQI0tj4Wrue3Eq3B3pmFU=
|
||||
github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
|
|
@ -255,11 +256,14 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8
|
|||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
|
||||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
|
||||
|
|
@ -347,5 +351,7 @@ gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHO
|
|||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
)
|
||||
|
||||
const (
|
||||
ConsensusEngineVersion1 = "v1"
|
||||
ConsensusEngineVersion2 = "v2"
|
||||
)
|
||||
|
||||
var (
|
||||
XDCMainnetGenesisHash = common.HexToHash("9326145f8a2c8c00bbe13afc7d7f3d9c868b5ef39d89f2f4e9390e9720298624") // XDC Mainnet genesis hash to enforce below configs on
|
||||
MainnetGenesisHash = common.HexToHash("8d13370621558f4ed0da587934473c0404729f28b0ff1d50e5fdd840457a2f17") // Mainnet genesis hash to enforce below configs on
|
||||
|
|
@ -111,10 +116,13 @@ var (
|
|||
// adding flags to the config to also have to set these fields.
|
||||
AllXDPoSProtocolChanges = &ChainConfig{big.NewInt(89), 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}
|
||||
|
||||
TestXDPoSChanConfig = &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: 2, Epoch: 900, Reward: 250, RewardCheckpoint: 900, Gap: 890, FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068")}}
|
||||
// XDPoS config in use for v1 engine only
|
||||
TestXDPoSMockChainConfig = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true}}
|
||||
TestXDPoSChanConfig = &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: 2, Epoch: 900, Reward: 250, RewardCheckpoint: 900, Gap: 890, FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068")}}
|
||||
// TestXDPoSMockChainConfig = &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, nil, nil, &XDPoSConfig{Epoch: 900, Gap: 890, SkipValidation: true}}
|
||||
// TestXDPoSChainConfig = &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, nil, nil, &XDPoSConfig{Period: 2, Epoch: 900, Reward: 250, RewardCheckpoint: 900, Gap: 890, FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068")}}
|
||||
// XDPoS config with v2 engine after block 10
|
||||
TestXDPoSMockChainConfigWithV2Engine = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, V2ConsensusBlockNumber: big.NewInt(10)}}
|
||||
|
||||
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))
|
||||
)
|
||||
|
|
@ -169,13 +177,14 @@ func (c *CliqueConfig) String() string {
|
|||
|
||||
// XDPoSConfig is the consensus engine configs for delegated-proof-of-stake based sealing.
|
||||
type XDPoSConfig struct {
|
||||
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
|
||||
Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint
|
||||
Reward uint64 `json:"reward"` // Block reward - unit Ether
|
||||
RewardCheckpoint uint64 `json:"rewardCheckpoint"` // Checkpoint block for calculate rewards.
|
||||
Gap uint64 `json:"gap"` // Gap time preparing for the next epoch
|
||||
FoudationWalletAddr common.Address `json:"foudationWalletAddr"` // Foundation Address Wallet
|
||||
SkipValidation bool //Skip Block Validation for testing purpose
|
||||
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
|
||||
Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint
|
||||
Reward uint64 `json:"reward"` // Block reward - unit Ether
|
||||
RewardCheckpoint uint64 `json:"rewardCheckpoint"` // Checkpoint block for calculate rewards.
|
||||
Gap uint64 `json:"gap"` // Gap time preparing for the next epoch
|
||||
FoudationWalletAddr common.Address `json:"foudationWalletAddr"` // Foundation Address Wallet
|
||||
SkipValidation bool //Skip Block Validation for testing purpose
|
||||
V2ConsensusBlockNumber *big.Int
|
||||
}
|
||||
|
||||
// String implements the stringer interface, returning the consensus engine details.
|
||||
|
|
@ -187,8 +196,11 @@ func (c *XDPoSConfig) String() string {
|
|||
ConsensusVersion will return the consensus version to use for the provided block number. The returned int represent its version
|
||||
TODO: It's a dummy value for now until the 2.0 consensus engine is fully implemented.
|
||||
*/
|
||||
func BlockConsensusVersion(num *big.Int) int {
|
||||
return 1
|
||||
func (c *XDPoSConfig) BlockConsensusVersion(num *big.Int) string {
|
||||
if c.V2ConsensusBlockNumber != nil && num.Cmp(c.V2ConsensusBlockNumber) > 0 {
|
||||
return ConsensusEngineVersion2
|
||||
}
|
||||
return ConsensusEngineVersion1
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
|
|
|
|||
46
tests/consensus/adaptor_test.go
Normal file
46
tests/consensus/adaptor_test.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package consensus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAdaptorShouldGetAuthorForDifferentConsensusVersion(t *testing.T) {
|
||||
blockchain, _, currentBlock := PrepareXDCTestBlockChain(t, 10, params.TestXDPoSMockChainConfigWithV2Engine)
|
||||
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
|
||||
|
||||
addressFromAdaptor, errorAdaptor := adaptor.Author(currentBlock.Header())
|
||||
if errorAdaptor != nil {
|
||||
t.Fatalf("Failed while trying to get Author from adaptor")
|
||||
}
|
||||
addressFromV1Engine, errV1 := adaptor.EngineV1.Author(currentBlock.Header())
|
||||
if errV1 != nil {
|
||||
t.Fatalf("Failed while trying to get Author from engine v1")
|
||||
}
|
||||
// Make sure the value is exactly the same as from V1 engine
|
||||
assert.Equal(t, addressFromAdaptor, addressFromV1Engine)
|
||||
|
||||
// Insert one more block to make it above 10, which means now we are on v2 of consensus engine
|
||||
// Insert block 11
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", 11)
|
||||
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
|
||||
block11, err := insertBlock(blockchain, 11, blockCoinBase, currentBlock, merkleRoot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addressFromAdaptor, errorAdaptor = adaptor.Author(block11.Header())
|
||||
if errorAdaptor != nil {
|
||||
t.Fatalf("Failed while trying to get Author from adaptor")
|
||||
}
|
||||
addressFromV2Engine, errV2 := adaptor.EngineV2.Author(block11.Header())
|
||||
if errV2 != nil {
|
||||
t.Fatalf("Failed while trying to get Author from engine v2")
|
||||
}
|
||||
// Make sure the value is exactly the same as from V2 engine
|
||||
assert.Equal(t, addressFromAdaptor, addressFromV2Engine)
|
||||
}
|
||||
|
|
@ -1,368 +1,18 @@
|
|||
package tests
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
contractValidator "github.com/XinFinOrg/XDPoSChain/contracts/validator/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
. "github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
type masterNodes map[string]big.Int
|
||||
type signersList map[string]bool
|
||||
|
||||
const GAP = int(450)
|
||||
|
||||
var (
|
||||
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||
acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
||||
acc3Key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
voterKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee04aefe388d1e14474d32c45c72ce7b7a")
|
||||
acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) //xdc703c4b2bD70c169f5717101CaeE543299Fc946C7
|
||||
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) //xdc0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
|
||||
acc3Addr = crypto.PubkeyToAddress(acc3Key.PublicKey) //xdc71562b71999873DB5b286dF957af199Ec94617F7
|
||||
voterAddr = crypto.PubkeyToAddress(voterKey.PublicKey) //xdc5F74529C0338546f82389402a01c31fB52c6f434
|
||||
chainID = int64(1337)
|
||||
)
|
||||
|
||||
func debugMessage(backend *backends.SimulatedBackend, signers signersList, t *testing.T) {
|
||||
ms := GetCandidateFromCurrentSmartContract(backend, t)
|
||||
fmt.Println("=== current smart contract")
|
||||
for nodeAddr, cap := range ms {
|
||||
if !strings.Contains(nodeAddr, "000000000000000000000000000000000000") { //remove defaults
|
||||
fmt.Println(nodeAddr, cap)
|
||||
}
|
||||
}
|
||||
fmt.Println("=== this block signer list")
|
||||
for signer := range signers {
|
||||
if !strings.Contains(signer, "000000000000000000000000000000000000") { //remove defaults
|
||||
fmt.Println(signer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getCommonBackend(t *testing.T) *backends.SimulatedBackend {
|
||||
|
||||
// initial helper backend
|
||||
contractBackendForSC := backends.NewXDCSimulatedBackend(core.GenesisAlloc{
|
||||
voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
}, 10000000)
|
||||
|
||||
transactOpts := bind.NewKeyedTransactor(voterKey)
|
||||
|
||||
var candidates []common.Address
|
||||
var caps []*big.Int
|
||||
defalutCap := new(big.Int)
|
||||
defalutCap.SetString("1000000000", 10)
|
||||
|
||||
for i := 1; i <= 16; i++ {
|
||||
addr := fmt.Sprintf("%02d", i)
|
||||
candidates = append(candidates, common.StringToAddress(addr)) // StringToAddress does not exist
|
||||
caps = append(caps, defalutCap)
|
||||
}
|
||||
|
||||
acc1Cap, acc2Cap, acc3Cap, voterCap := new(big.Int), new(big.Int), new(big.Int), new(big.Int)
|
||||
|
||||
acc1Cap.SetString("10000001", 10)
|
||||
acc2Cap.SetString("10000002", 10)
|
||||
acc3Cap.SetString("10000003", 10)
|
||||
voterCap.SetString("1000000000", 10)
|
||||
|
||||
caps = append(caps, voterCap, acc1Cap, acc2Cap, acc3Cap)
|
||||
candidates = append(candidates, voterAddr, acc1Addr, acc2Addr, acc3Addr)
|
||||
// create validator smart contract
|
||||
validatorSCAddr, _, _, err := contractValidator.DeployXDCValidator(
|
||||
transactOpts,
|
||||
contractBackendForSC,
|
||||
candidates,
|
||||
caps,
|
||||
voterAddr, // first owner, not used
|
||||
big.NewInt(50000),
|
||||
big.NewInt(1),
|
||||
big.NewInt(99),
|
||||
big.NewInt(100),
|
||||
big.NewInt(100),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("can't deploy root registry: %v", err)
|
||||
}
|
||||
|
||||
contractBackendForSC.Commit() // Write into database(state)
|
||||
|
||||
// Prepare Code and Storage
|
||||
d := time.Now().Add(1000 * time.Millisecond)
|
||||
ctx, cancel := context.WithDeadline(context.Background(), d)
|
||||
defer cancel()
|
||||
|
||||
code, _ := contractBackendForSC.CodeAt(ctx, validatorSCAddr, nil)
|
||||
storage := make(map[common.Hash]common.Hash)
|
||||
f := func(key, val common.Hash) bool {
|
||||
decode := []byte{}
|
||||
trim := bytes.TrimLeft(val.Bytes(), "\x00")
|
||||
rlp.DecodeBytes(trim, &decode)
|
||||
storage[key] = common.BytesToHash(decode)
|
||||
log.Info("DecodeBytes", "value", val.String(), "decode", storage[key].String())
|
||||
return true
|
||||
}
|
||||
contractBackendForSC.ForEachStorageAt(ctx, validatorSCAddr, nil, f)
|
||||
|
||||
// create test backend with smart contract in it
|
||||
contractBackend2 := backends.NewXDCSimulatedBackend(core.GenesisAlloc{
|
||||
acc1Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
acc2Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
acc3Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
common.HexToAddress(common.MasternodeVotingSMC): {Balance: new(big.Int).SetUint64(1), Code: code, Storage: storage}, // Binding the MasternodeVotingSMC with newly created 'code' for SC execution
|
||||
}, 10000000)
|
||||
|
||||
return contractBackend2
|
||||
|
||||
}
|
||||
|
||||
func transferTx(t *testing.T, to common.Address, transferAmount int64) *types.Transaction {
|
||||
t.Logf("Transfering %v to address: %v", transferAmount, to.String())
|
||||
data := []byte{}
|
||||
gasPrice := big.NewInt(int64(0))
|
||||
gasLimit := uint64(21000)
|
||||
amount := big.NewInt(transferAmount)
|
||||
nonce := uint64(1)
|
||||
tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
|
||||
signedTX, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), voterKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return signedTX
|
||||
}
|
||||
|
||||
/*
|
||||
func proposeTX(t *testing.T) *types.Transaction {
|
||||
data := common.Hex2Bytes("012679510000000000000000000000000d3ab14bbad3d99f4203bd7a11acb94882050e7e")
|
||||
//data := []byte{}
|
||||
fmt.Println("data", string(data[:]))
|
||||
gasPrice := big.NewInt(int64(0))
|
||||
gasLimit := uint64(22680)
|
||||
amountInt := new(big.Int)
|
||||
amount, ok := amountInt.SetString("11000000000000000000000000", 10)
|
||||
if !ok {
|
||||
t.Fatal("big int init failed")
|
||||
}
|
||||
nonce := uint64(0)
|
||||
to := common.HexToAddress("xdc35658f7b2a9e7701e65e7a654659eb1c481d1dc5")
|
||||
tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
|
||||
signedTX, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), acc4Key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return signedTX
|
||||
}
|
||||
*/
|
||||
|
||||
func voteTX(gasLimit uint64, nonce uint64, addr string) (*types.Transaction, error) {
|
||||
vote := "6dd7d8ea" // VoteMethod = "0x6dd7d8ea"
|
||||
action := fmt.Sprintf("%s%s%s", vote, "000000000000000000000000", addr[3:])
|
||||
data := common.Hex2Bytes(action)
|
||||
gasPrice := big.NewInt(int64(0))
|
||||
amountInt := new(big.Int)
|
||||
amount, ok := amountInt.SetString("60000", 10)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("big int init failed")
|
||||
}
|
||||
to := common.HexToAddress(common.MasternodeVotingSMC)
|
||||
tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
|
||||
|
||||
signedTX, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), voterKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signedTX, nil
|
||||
}
|
||||
|
||||
func UpdateSigner(bc *BlockChain) error {
|
||||
err := bc.UpdateM1()
|
||||
return err
|
||||
}
|
||||
|
||||
func GetSnapshotSigner(bc *BlockChain, header *types.Header) (signersList, error) {
|
||||
engine := bc.Engine().(*XDPoS.XDPoS)
|
||||
snap, err := engine.GetSnapshot(bc, header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
ms := make(signersList)
|
||||
|
||||
for addr := range snap.Signers {
|
||||
ms[addr.Hex()] = true
|
||||
}
|
||||
return ms, nil
|
||||
|
||||
}
|
||||
|
||||
func GetCandidateFromCurrentSmartContract(backend bind.ContractBackend, t *testing.T) masterNodes {
|
||||
addr := common.HexToAddress(common.MasternodeVotingSMC)
|
||||
validator, err := contractValidator.NewXDCValidator(addr, backend)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
opts := new(bind.CallOpts)
|
||||
candidates, err := validator.GetCandidates(opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ms := make(masterNodes)
|
||||
for _, candidate := range candidates {
|
||||
v, err := validator.GetCandidateCap(opts, candidate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ms[candidate.String()] = *v
|
||||
}
|
||||
return ms
|
||||
}
|
||||
|
||||
func PrepareXDCTestBlockChain(t *testing.T, numOfBlocks int) (*BlockChain, *backends.SimulatedBackend, *types.Block) {
|
||||
// Preparation
|
||||
var err error
|
||||
backend := getCommonBackend(t)
|
||||
blockchain := backend.GetBlockChain()
|
||||
blockchain.Client = backend
|
||||
|
||||
currentBlock := blockchain.Genesis()
|
||||
|
||||
// Insert initial blocks
|
||||
for i := 1; i <= numOfBlocks; i++ {
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
|
||||
block, err := insertBlock(blockchain, i, blockCoinBase, currentBlock, merkleRoot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
currentBlock = block
|
||||
}
|
||||
// Update Signer as there is no previous signer assigned
|
||||
err = UpdateSigner(blockchain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return blockchain, backend, currentBlock
|
||||
}
|
||||
|
||||
// insert Block without transcation attached
|
||||
func insertBlock(blockchain *BlockChain, blockNum int, blockCoinBase string, parentBlock *types.Block, root string) (*types.Block, error) {
|
||||
block, err := createXDPoSTestBlock(
|
||||
blockchain,
|
||||
parentBlock.Hash().Hex(),
|
||||
blockCoinBase, blockNum, nil,
|
||||
"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
common.HexToHash(root),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = blockchain.InsertBlock(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// insert Block with transcation attached
|
||||
func insertBlockTxs(blockchain *BlockChain, blockNum int, blockCoinBase string, parentBlock *types.Block, txs []*types.Transaction, root string) (*types.Block, error) {
|
||||
block, err := createXDPoSTestBlock(
|
||||
blockchain,
|
||||
parentBlock.Hash().Hex(),
|
||||
blockCoinBase, blockNum, txs,
|
||||
"0x9319777b782ba2c83a33c995481ff894ac96d9a92a1963091346a3e1e386705c",
|
||||
common.HexToHash(root),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = blockchain.InsertBlock(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return block, nil
|
||||
}
|
||||
|
||||
func createXDPoSTestBlock(bc *BlockChain, parentHash, coinbase string, number int, txs []*types.Transaction, receiptHash string, root common.Hash) (*types.Block, error) {
|
||||
extraSubstring := "d7830100018358444388676f312e31342e31856c696e75780000000000000000b185dc0d0e917d18e5dbf0746be6597d3331dd27ea0554e6db433feb2e81730b20b2807d33a1527bf43cd3bc057aa7f641609c2551ebe2fd575f4db704fbf38101" // Grabbed from existing mainnet block, it does not have any meaning except for the length validation
|
||||
//ReceiptHash = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
|
||||
//Root := "0xc99c095e53ff1afe3b86750affd13c7550a2d24d51fb8e41b3c3ef2ea8274bcc"
|
||||
extraByte, _ := hex.DecodeString(extraSubstring)
|
||||
header := types.Header{
|
||||
ParentHash: common.HexToHash(parentHash),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
// ReceiptHash: types.EmptyRootHash,
|
||||
ReceiptHash: common.HexToHash(receiptHash),
|
||||
Root: root,
|
||||
Coinbase: common.HexToAddress(coinbase),
|
||||
Difficulty: big.NewInt(int64(1)),
|
||||
Number: big.NewInt(int64(number)),
|
||||
GasLimit: 1200000000,
|
||||
Time: big.NewInt(int64(number * 10)),
|
||||
Extra: extraByte,
|
||||
}
|
||||
|
||||
var block *types.Block
|
||||
if len(txs) == 0 {
|
||||
block = types.NewBlockWithHeader(&header)
|
||||
} else {
|
||||
|
||||
// Prepare Receipt
|
||||
statedb, err := bc.StateAt(bc.GetBlockByNumber(uint64(number - 1)).Root()) //Get parent root
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v when get state", err)
|
||||
}
|
||||
gp := new(GasPool).AddGas(header.GasLimit)
|
||||
// usedGas := uint64(0)
|
||||
|
||||
var gasUsed = new(uint64)
|
||||
var receipts types.Receipts
|
||||
for i, tx := range txs {
|
||||
statedb.Prepare(tx.Hash(), header.Hash(), i)
|
||||
receipt, _, err, _ := ApplyTransaction(bc.Config(), nil, bc, &header.Coinbase, gp, statedb, nil, &header, tx, gasUsed, vm.Config{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v when applying transaction", err)
|
||||
}
|
||||
receipts = append(receipts, receipt)
|
||||
}
|
||||
|
||||
header.GasUsed = *gasUsed
|
||||
|
||||
block = types.NewBlock(&header, txs, nil, receipts)
|
||||
}
|
||||
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// Should NOT update signerList if not on the gap block
|
||||
func TestNotUpdateSignerListIfNotOnGapBlock(t *testing.T) {
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, 400)
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, 400, params.TestXDPoSMockChainConfig)
|
||||
parentSigners, err := GetSnapshotSigner(blockchain, parentBlock.Header())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -400,7 +50,7 @@ func TestNotUpdateSignerListIfNotOnGapBlock(t *testing.T) {
|
|||
|
||||
// Should call updateM1 at the gap block, and have the same snapshot values as the parent block if no SM transaction is involved
|
||||
func TestNotChangeSingerListIfNothingProposedOrVoted(t *testing.T) {
|
||||
blockchain, _, parentBlock := PrepareXDCTestBlockChain(t, GAP-1)
|
||||
blockchain, _, parentBlock := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig)
|
||||
// Insert block 450
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", 450)
|
||||
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
|
||||
|
|
@ -428,7 +78,7 @@ func TestNotChangeSingerListIfNothingProposedOrVoted(t *testing.T) {
|
|||
//Should call updateM1 at gap block, and update the snapshot if there are SM transactions involved
|
||||
func TestUpdateSignerListIfVotedBeforeGap(t *testing.T) {
|
||||
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, GAP-2)
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, GAP-2, params.TestXDPoSMockChainConfig)
|
||||
// Insert first Block 449
|
||||
t.Logf("Inserting block with propose at 449...")
|
||||
blockCoinbaseA := "0xaaa0000000000000000000000000000000000449"
|
||||
|
|
@ -469,6 +119,9 @@ func TestUpdateSignerListIfVotedBeforeGap(t *testing.T) {
|
|||
}
|
||||
|
||||
signers, err = GetSnapshotSigner(blockchain, block450.Header())
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while trying to get signers")
|
||||
}
|
||||
// Now, we voted acc 1 to be in the signerList, which will kick out acc3 because it has less funds
|
||||
if signers[acc3Addr.Hex()] == true {
|
||||
debugMessage(backend, signers, t)
|
||||
|
|
@ -483,7 +136,7 @@ func TestUpdateSignerListIfVotedBeforeGap(t *testing.T) {
|
|||
//Should call updateM1 before gap block, and update the snapshot if there are SM transactions involved
|
||||
func TestCallUpdateM1WithSmartContractTranscation(t *testing.T) {
|
||||
|
||||
blockchain, backend, currentBlock := PrepareXDCTestBlockChain(t, GAP-1)
|
||||
blockchain, backend, currentBlock := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig)
|
||||
// Insert first Block 450 A
|
||||
t.Logf("Inserting block with propose at 450 A...")
|
||||
blockCoinbaseA := "0xaaa0000000000000000000000000000000000450"
|
||||
|
|
@ -512,7 +165,7 @@ func TestCallUpdateM1WithSmartContractTranscation(t *testing.T) {
|
|||
// Should call updateM1 and update snapshot when a forked block(at gap block number) is inserted back into main chain (Edge case)
|
||||
func TestCallUpdateM1WhenForkedBlockBackToMainChain(t *testing.T) {
|
||||
|
||||
blockchain, backend, currentBlock := PrepareXDCTestBlockChain(t, GAP-1)
|
||||
blockchain, backend, currentBlock := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig)
|
||||
// Check initial signer, by default, acc3 is in the signerList
|
||||
signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header())
|
||||
if err != nil {
|
||||
|
|
@ -635,9 +288,12 @@ func TestCallUpdateM1WhenForkedBlockBackToMainChain(t *testing.T) {
|
|||
|
||||
func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testing.T) {
|
||||
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, GAP-1)
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig)
|
||||
|
||||
state, err := blockchain.State()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while trying to get blockchain state")
|
||||
}
|
||||
t.Logf("Account %v have balance of: %v", acc1Addr.String(), state.GetBalance(acc1Addr))
|
||||
// Check initial signer
|
||||
signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header())
|
||||
|
|
@ -665,6 +321,9 @@ func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testin
|
|||
t.Fatal(err)
|
||||
}
|
||||
state, err = blockchain.State()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while trying to get blockchain state")
|
||||
}
|
||||
t.Log("After transfer transaction at block 450 A, Account 1 have balance of: ", state.GetBalance(acc1Addr))
|
||||
|
||||
if state.GetBalance(acc1Addr).Cmp(new(big.Int).SetUint64(10000000999)) != 0 {
|
||||
|
|
@ -697,6 +356,9 @@ func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testin
|
|||
t.Fatal(err)
|
||||
}
|
||||
state, err = blockchain.State()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while trying to get blockchain state")
|
||||
}
|
||||
if state.GetBalance(acc1Addr).Cmp(new(big.Int).SetUint64(10000000999)) != 0 {
|
||||
t.Fatalf("account 1 should have 10000000999 in balance as the block is forked, not on the main chain")
|
||||
}
|
||||
|
|
@ -749,6 +411,9 @@ func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testin
|
|||
t.Fatalf("acc2Addr should sit in the signer list")
|
||||
}
|
||||
state, err = blockchain.State()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while trying to get blockchain state")
|
||||
}
|
||||
t.Log("After transfer transaction at block 450 B and the B fork has been merged into main chain, Account 1 have balance of: ", state.GetBalance(acc1Addr))
|
||||
|
||||
if state.GetBalance(acc1Addr).Cmp(new(big.Int).SetUint64(10000000888)) != 0 {
|
||||
|
|
@ -757,7 +422,7 @@ func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testin
|
|||
}
|
||||
|
||||
func TestVoteShouldNotBeAffectedByFork(t *testing.T) {
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, GAP-1)
|
||||
blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig)
|
||||
// Check initial signer, by default, acc3 is in the signerList
|
||||
signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header())
|
||||
if err != nil {
|
||||
367
tests/consensus/test_helper.go
Normal file
367
tests/consensus/test_helper.go
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
package consensus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
contractValidator "github.com/XinFinOrg/XDPoSChain/contracts/validator/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
. "github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
)
|
||||
|
||||
type masterNodes map[string]big.Int
|
||||
type signersList map[string]bool
|
||||
|
||||
const GAP = int(450)
|
||||
|
||||
var (
|
||||
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||
acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
||||
acc3Key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
voterKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee04aefe388d1e14474d32c45c72ce7b7a")
|
||||
acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) //xdc703c4b2bD70c169f5717101CaeE543299Fc946C7
|
||||
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) //xdc0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
|
||||
acc3Addr = crypto.PubkeyToAddress(acc3Key.PublicKey) //xdc71562b71999873DB5b286dF957af199Ec94617F7
|
||||
voterAddr = crypto.PubkeyToAddress(voterKey.PublicKey) //xdc5F74529C0338546f82389402a01c31fB52c6f434
|
||||
chainID = int64(1337)
|
||||
)
|
||||
|
||||
func debugMessage(backend *backends.SimulatedBackend, signers signersList, t *testing.T) {
|
||||
ms := GetCandidateFromCurrentSmartContract(backend, t)
|
||||
fmt.Println("=== current smart contract")
|
||||
for nodeAddr, cap := range ms {
|
||||
if !strings.Contains(nodeAddr, "000000000000000000000000000000000000") { //remove defaults
|
||||
fmt.Println(nodeAddr, cap)
|
||||
}
|
||||
}
|
||||
fmt.Println("=== this block signer list")
|
||||
for signer := range signers {
|
||||
if !strings.Contains(signer, "000000000000000000000000000000000000") { //remove defaults
|
||||
fmt.Println(signer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getCommonBackend(t *testing.T, chainConfig *params.ChainConfig) *backends.SimulatedBackend {
|
||||
|
||||
// initial helper backend
|
||||
contractBackendForSC := backends.NewXDCSimulatedBackend(core.GenesisAlloc{
|
||||
voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
}, 10000000, chainConfig)
|
||||
|
||||
transactOpts := bind.NewKeyedTransactor(voterKey)
|
||||
|
||||
var candidates []common.Address
|
||||
var caps []*big.Int
|
||||
defalutCap := new(big.Int)
|
||||
defalutCap.SetString("1000000000", 10)
|
||||
|
||||
for i := 1; i <= 16; i++ {
|
||||
addr := fmt.Sprintf("%02d", i)
|
||||
candidates = append(candidates, common.StringToAddress(addr)) // StringToAddress does not exist
|
||||
caps = append(caps, defalutCap)
|
||||
}
|
||||
|
||||
acc1Cap, acc2Cap, acc3Cap, voterCap := new(big.Int), new(big.Int), new(big.Int), new(big.Int)
|
||||
|
||||
acc1Cap.SetString("10000001", 10)
|
||||
acc2Cap.SetString("10000002", 10)
|
||||
acc3Cap.SetString("10000003", 10)
|
||||
voterCap.SetString("1000000000", 10)
|
||||
|
||||
caps = append(caps, voterCap, acc1Cap, acc2Cap, acc3Cap)
|
||||
candidates = append(candidates, voterAddr, acc1Addr, acc2Addr, acc3Addr)
|
||||
// create validator smart contract
|
||||
validatorSCAddr, _, _, err := contractValidator.DeployXDCValidator(
|
||||
transactOpts,
|
||||
contractBackendForSC,
|
||||
candidates,
|
||||
caps,
|
||||
voterAddr, // first owner, not used
|
||||
big.NewInt(50000),
|
||||
big.NewInt(1),
|
||||
big.NewInt(99),
|
||||
big.NewInt(100),
|
||||
big.NewInt(100),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("can't deploy root registry: %v", err)
|
||||
}
|
||||
|
||||
contractBackendForSC.Commit() // Write into database(state)
|
||||
|
||||
// Prepare Code and Storage
|
||||
d := time.Now().Add(1000 * time.Millisecond)
|
||||
ctx, cancel := context.WithDeadline(context.Background(), d)
|
||||
defer cancel()
|
||||
|
||||
code, _ := contractBackendForSC.CodeAt(ctx, validatorSCAddr, nil)
|
||||
storage := make(map[common.Hash]common.Hash)
|
||||
f := func(key, val common.Hash) bool {
|
||||
decode := []byte{}
|
||||
trim := bytes.TrimLeft(val.Bytes(), "\x00")
|
||||
err := rlp.DecodeBytes(trim, &decode)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while decode byte")
|
||||
}
|
||||
storage[key] = common.BytesToHash(decode)
|
||||
log.Info("DecodeBytes", "value", val.String(), "decode", storage[key].String())
|
||||
return true
|
||||
}
|
||||
err = contractBackendForSC.ForEachStorageAt(ctx, validatorSCAddr, nil, f)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while trying to read all keys from SC")
|
||||
}
|
||||
|
||||
// create test backend with smart contract in it
|
||||
contractBackend2 := backends.NewXDCSimulatedBackend(core.GenesisAlloc{
|
||||
acc1Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
acc2Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
acc3Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
common.HexToAddress(common.MasternodeVotingSMC): {Balance: new(big.Int).SetUint64(1), Code: code, Storage: storage}, // Binding the MasternodeVotingSMC with newly created 'code' for SC execution
|
||||
}, 10000000, chainConfig)
|
||||
|
||||
return contractBackend2
|
||||
|
||||
}
|
||||
|
||||
func transferTx(t *testing.T, to common.Address, transferAmount int64) *types.Transaction {
|
||||
t.Logf("Transfering %v to address: %v", transferAmount, to.String())
|
||||
data := []byte{}
|
||||
gasPrice := big.NewInt(int64(0))
|
||||
gasLimit := uint64(21000)
|
||||
amount := big.NewInt(transferAmount)
|
||||
nonce := uint64(1)
|
||||
tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
|
||||
signedTX, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), voterKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return signedTX
|
||||
}
|
||||
|
||||
func voteTX(gasLimit uint64, nonce uint64, addr string) (*types.Transaction, error) {
|
||||
vote := "6dd7d8ea" // VoteMethod = "0x6dd7d8ea"
|
||||
action := fmt.Sprintf("%s%s%s", vote, "000000000000000000000000", addr[3:])
|
||||
data := common.Hex2Bytes(action)
|
||||
gasPrice := big.NewInt(int64(0))
|
||||
amountInt := new(big.Int)
|
||||
amount, ok := amountInt.SetString("60000", 10)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("big int init failed")
|
||||
}
|
||||
to := common.HexToAddress(common.MasternodeVotingSMC)
|
||||
tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
|
||||
|
||||
signedTX, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), voterKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signedTX, nil
|
||||
}
|
||||
|
||||
func UpdateSigner(bc *BlockChain) error {
|
||||
err := bc.UpdateM1()
|
||||
return err
|
||||
}
|
||||
|
||||
func GetSnapshotSigner(bc *BlockChain, header *types.Header) (signersList, error) {
|
||||
engine := bc.Engine().(*XDPoS.XDPoS)
|
||||
snap, err := engine.GetSnapshot(bc, header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
ms := make(signersList)
|
||||
|
||||
for addr := range snap.Signers {
|
||||
ms[addr.Hex()] = true
|
||||
}
|
||||
return ms, nil
|
||||
|
||||
}
|
||||
|
||||
func GetCandidateFromCurrentSmartContract(backend bind.ContractBackend, t *testing.T) masterNodes {
|
||||
addr := common.HexToAddress(common.MasternodeVotingSMC)
|
||||
validator, err := contractValidator.NewXDCValidator(addr, backend)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
opts := new(bind.CallOpts)
|
||||
candidates, err := validator.GetCandidates(opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ms := make(masterNodes)
|
||||
for _, candidate := range candidates {
|
||||
v, err := validator.GetCandidateCap(opts, candidate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ms[candidate.String()] = *v
|
||||
}
|
||||
return ms
|
||||
}
|
||||
|
||||
func PrepareXDCTestBlockChain(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig) (*BlockChain, *backends.SimulatedBackend, *types.Block) {
|
||||
// Preparation
|
||||
var err error
|
||||
backend := getCommonBackend(t, chainConfig)
|
||||
blockchain := backend.GetBlockChain()
|
||||
blockchain.Client = backend
|
||||
|
||||
currentBlock := blockchain.Genesis()
|
||||
|
||||
// Insert initial blocks
|
||||
for i := 1; i <= numOfBlocks; i++ {
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
|
||||
block, err := insertBlock(blockchain, i, blockCoinBase, currentBlock, merkleRoot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
currentBlock = block
|
||||
}
|
||||
// Update Signer as there is no previous signer assigned
|
||||
err = UpdateSigner(blockchain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return blockchain, backend, currentBlock
|
||||
}
|
||||
|
||||
// insert Block without transcation attached
|
||||
func insertBlock(blockchain *BlockChain, blockNum int, blockCoinBase string, parentBlock *types.Block, root string) (*types.Block, error) {
|
||||
block, err := createXDPoSTestBlock(
|
||||
blockchain,
|
||||
parentBlock.Hash().Hex(),
|
||||
blockCoinBase, blockNum, nil,
|
||||
"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
common.HexToHash(root),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = blockchain.InsertBlock(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// insert Block with transcation attached
|
||||
func insertBlockTxs(blockchain *BlockChain, blockNum int, blockCoinBase string, parentBlock *types.Block, txs []*types.Transaction, root string) (*types.Block, error) {
|
||||
block, err := createXDPoSTestBlock(
|
||||
blockchain,
|
||||
parentBlock.Hash().Hex(),
|
||||
blockCoinBase, blockNum, txs,
|
||||
"0x9319777b782ba2c83a33c995481ff894ac96d9a92a1963091346a3e1e386705c",
|
||||
common.HexToHash(root),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = blockchain.InsertBlock(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return block, nil
|
||||
}
|
||||
|
||||
func createXDPoSTestBlock(bc *BlockChain, parentHash, coinbase string, number int, txs []*types.Transaction, receiptHash string, root common.Hash) (*types.Block, error) {
|
||||
extraSubstring := "d7830100018358444388676f312e31342e31856c696e75780000000000000000b185dc0d0e917d18e5dbf0746be6597d3331dd27ea0554e6db433feb2e81730b20b2807d33a1527bf43cd3bc057aa7f641609c2551ebe2fd575f4db704fbf38101" // Grabbed from existing mainnet block, it does not have any meaning except for the length validation
|
||||
//ReceiptHash = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
|
||||
//Root := "0xc99c095e53ff1afe3b86750affd13c7550a2d24d51fb8e41b3c3ef2ea8274bcc"
|
||||
extraByte, _ := hex.DecodeString(extraSubstring)
|
||||
header := types.Header{
|
||||
ParentHash: common.HexToHash(parentHash),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
// ReceiptHash: types.EmptyRootHash,
|
||||
ReceiptHash: common.HexToHash(receiptHash),
|
||||
Root: root,
|
||||
Coinbase: common.HexToAddress(coinbase),
|
||||
Difficulty: big.NewInt(int64(1)),
|
||||
Number: big.NewInt(int64(number)),
|
||||
GasLimit: 1200000000,
|
||||
Time: big.NewInt(int64(number * 10)),
|
||||
Extra: extraByte,
|
||||
}
|
||||
|
||||
var block *types.Block
|
||||
if len(txs) == 0 {
|
||||
block = types.NewBlockWithHeader(&header)
|
||||
} else {
|
||||
|
||||
// Prepare Receipt
|
||||
statedb, err := bc.StateAt(bc.GetBlockByNumber(uint64(number - 1)).Root()) //Get parent root
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v when get state", err)
|
||||
}
|
||||
gp := new(GasPool).AddGas(header.GasLimit)
|
||||
// usedGas := uint64(0)
|
||||
|
||||
var gasUsed = new(uint64)
|
||||
var receipts types.Receipts
|
||||
for i, tx := range txs {
|
||||
statedb.Prepare(tx.Hash(), header.Hash(), i)
|
||||
receipt, _, err, _ := ApplyTransaction(bc.Config(), nil, bc, &header.Coinbase, gp, statedb, nil, &header, tx, gasUsed, vm.Config{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v when applying transaction", err)
|
||||
}
|
||||
receipts = append(receipts, receipt)
|
||||
}
|
||||
|
||||
header.GasUsed = *gasUsed
|
||||
|
||||
block = types.NewBlock(&header, txs, nil, receipts)
|
||||
}
|
||||
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// /*
|
||||
// func proposeTX(t *testing.T) *types.Transaction {
|
||||
// data := common.Hex2Bytes("012679510000000000000000000000000d3ab14bbad3d99f4203bd7a11acb94882050e7e")
|
||||
// //data := []byte{}
|
||||
// fmt.Println("data", string(data[:]))
|
||||
// gasPrice := big.NewInt(int64(0))
|
||||
// gasLimit := uint64(22680)
|
||||
// amountInt := new(big.Int)
|
||||
// amount, ok := amountInt.SetString("11000000000000000000000000", 10)
|
||||
// if !ok {
|
||||
// t.Fatal("big int init failed")
|
||||
// }
|
||||
// nonce := uint64(0)
|
||||
// to := common.HexToAddress("xdc35658f7b2a9e7701e65e7a654659eb1c481d1dc5")
|
||||
// tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
|
||||
// signedTX, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), acc4Key)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// return signedTX
|
||||
// }
|
||||
// */
|
||||
Loading…
Reference in a new issue