Merge pull request #12 from hash-laboratories-au/adaptor-config-setup-with-tests

Adaptor config setup with tests
This commit is contained in:
Jerome 2021-10-17 12:57:33 +11:00 committed by GitHub
commit a996c3a1a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 900 additions and 31233 deletions

View file

@ -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{

View file

@ -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)

View file

@ -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.

View file

@ -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)

View file

@ -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)
}

View file

@ -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())
}

View file

@ -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)

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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))

View file

@ -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) {

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

2
go.mod
View file

@ -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
View file

@ -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=

View file

@ -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.

View 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)
}

View file

@ -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 {

View 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
// }
// */