Merge pull request #343 from XinFinOrg/dev-upgrade

gas upgrade and testnet v2 switch block correction
This commit is contained in:
Anil Chinchawale 2023-11-02 12:54:32 +05:30 committed by GitHub
commit 1ad2b297b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 295 additions and 202 deletions

View file

@ -2,16 +2,15 @@ package lendingstate
import ( import (
"encoding/json" "encoding/json"
"github.com/XinFinOrg/XDPoSChain/crypto"
"math/big" "math/big"
"time" "time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/crypto"
) )
var ( var (
EmptyAddress = "xdc0000000000000000000000000000000000000000" EmptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
EmptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
) )
var EmptyHash = common.Hash{} var EmptyHash = common.Hash{}

View file

@ -2,14 +2,15 @@ package lendingstate
import ( import (
"fmt" "fmt"
"math/big"
"strconv"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/crypto/sha3" "github.com/XinFinOrg/XDPoSChain/crypto/sha3"
"github.com/globalsign/mgo/bson" "github.com/globalsign/mgo/bson"
"math/big"
"strconv"
"time"
) )
const ( const (
@ -243,7 +244,7 @@ func (l *LendingItem) VerifyLendingSide() error {
} }
func (l *LendingItem) VerifyCollateral(state *state.StateDB) error { func (l *LendingItem) VerifyCollateral(state *state.StateDB) error {
if l.CollateralToken.String() == EmptyAddress || l.CollateralToken.String() == l.LendingToken.String() { if l.CollateralToken.IsZero() || l.CollateralToken == l.LendingToken {
return fmt.Errorf("invalid collateral %s", l.CollateralToken.Hex()) return fmt.Errorf("invalid collateral %s", l.CollateralToken.Hex())
} }
validCollateral := false validCollateral := false
@ -329,7 +330,7 @@ func (l *LendingItem) EncodedSide() *big.Int {
return big.NewInt(1) return big.NewInt(1)
} }
//verify signatures // verify signatures
func (l *LendingItem) VerifyLendingSignature() error { func (l *LendingItem) VerifyLendingSignature() error {
V := big.NewInt(int64(l.Signature.V)) V := big.NewInt(int64(l.Signature.V))
R := l.Signature.R.Big() R := l.Signature.R.Big()

View file

@ -3,6 +3,8 @@ package XDCxlending
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/big"
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate" "github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -10,7 +12,6 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/log"
"math/big"
) )
func (l *Lending) CommitOrder(header *types.Header, coinbase common.Address, chain consensus.ChainContext, statedb *state.StateDB, lendingStateDB *lendingstate.LendingStateDB, tradingStateDb *tradingstate.TradingStateDB, lendingOrderBook common.Hash, order *lendingstate.LendingItem) ([]*lendingstate.LendingTrade, []*lendingstate.LendingItem, error) { func (l *Lending) CommitOrder(header *types.Header, coinbase common.Address, chain consensus.ChainContext, statedb *state.StateDB, lendingStateDB *lendingstate.LendingStateDB, tradingStateDb *tradingstate.TradingStateDB, lendingOrderBook common.Hash, order *lendingstate.LendingItem) ([]*lendingstate.LendingTrade, []*lendingstate.LendingItem, error) {
@ -262,10 +263,9 @@ func (l *Lending) processOrderList(header *types.Header, coinbase common.Address
collateralToken = oldestOrder.CollateralToken collateralToken = oldestOrder.CollateralToken
borrowFee = lendingstate.GetFee(statedb, oldestOrder.Relayer) borrowFee = lendingstate.GetFee(statedb, oldestOrder.Relayer)
} }
if collateralToken.String() == lendingstate.EmptyAddress { if collateralToken.IsZero() {
return nil, nil, nil, fmt.Errorf("empty collateral") return nil, nil, nil, fmt.Errorf("empty collateral")
} }
collateralPrice := common.BasePrice
depositRate, liquidationRate, recallRate := lendingstate.GetCollateralDetail(statedb, collateralToken) depositRate, liquidationRate, recallRate := lendingstate.GetCollateralDetail(statedb, collateralToken)
if depositRate == nil || depositRate.Sign() <= 0 { if depositRate == nil || depositRate.Sign() <= 0 {
return nil, nil, nil, fmt.Errorf("invalid depositRate %v", depositRate) return nil, nil, nil, fmt.Errorf("invalid depositRate %v", depositRate)
@ -953,11 +953,11 @@ func (l *Lending) GetMediumTradePriceBeforeEpoch(chain consensus.ChainContext, s
return nil, nil return nil, nil
} }
//LendToken and CollateralToken must meet at least one of following conditions // LendToken and CollateralToken must meet at least one of following conditions
//- Have direct pair in XDCX: lendToken/CollateralToken or CollateralToken/LendToken // - Have direct pair in XDCX: lendToken/CollateralToken or CollateralToken/LendToken
//- Have pairs with XDC: // - Have pairs with XDC:
//- lendToken/XDC and CollateralToken/XDC // - lendToken/XDC and CollateralToken/XDC
//- XDC/lendToken and XDC/CollateralToken // - XDC/lendToken and XDC/CollateralToken
func (l *Lending) GetCollateralPrices(header *types.Header, chain consensus.ChainContext, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, collateralToken common.Address, lendingToken common.Address) (*big.Int, *big.Int, error) { func (l *Lending) GetCollateralPrices(header *types.Header, chain consensus.ChainContext, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, collateralToken common.Address, lendingToken common.Address) (*big.Int, *big.Int, error) {
// lendTokenXDCPrice: price of ticker lendToken/XDC // lendTokenXDCPrice: price of ticker lendToken/XDC
// collateralXDCPrice: price of ticker collateralToken/XDC // collateralXDCPrice: price of ticker collateralToken/XDC

View file

@ -128,7 +128,7 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
return err return err
} }
var ( var (
msg = XDPoSChain.CallMsg{From: opts.From, To: &c.address, Data: input, GasPrice: common.MinGasPrice, Gas: uint64(4200000)} msg = XDPoSChain.CallMsg{From: opts.From, To: &c.address, Data: input, GasPrice: common.MinGasPrice50x, Gas: uint64(4200000)}
ctx = ensureContext(opts.Context) ctx = ensureContext(opts.Context)
code []byte code []byte
output []byte output []byte

View file

@ -185,6 +185,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) {
common.MinGasPrice = big.NewInt(gasPrice) common.MinGasPrice = big.NewInt(gasPrice)
} }
} }
common.MinGasPrice50x = common.MinGasPrice50x.Mul(common.MinGasPrice, big.NewInt(50))
// read passwords from environment // read passwords from environment
passwords := []string{} passwords := []string{}

View file

@ -77,7 +77,7 @@ func (w *wizard) makeGenesis() {
genesis.Difficulty = big.NewInt(1) genesis.Difficulty = big.NewInt(1)
genesis.Config.Clique = &params.CliqueConfig{ genesis.Config.Clique = &params.CliqueConfig{
Period: 15, Period: 15,
Epoch: 30000, Epoch: 900,
} }
fmt.Println() fmt.Println()
fmt.Println("How many seconds should blocks take? (default = 15)") fmt.Println("How many seconds should blocks take? (default = 15)")
@ -114,7 +114,7 @@ func (w *wizard) makeGenesis() {
genesis.Difficulty = big.NewInt(1) genesis.Difficulty = big.NewInt(1)
genesis.Config.XDPoS = &params.XDPoSConfig{ genesis.Config.XDPoS = &params.XDPoSConfig{
Period: 15, Period: 15,
Epoch: 30000, Epoch: 900,
Reward: 0, Reward: 0,
V2: &params.V2{ V2: &params.V2{
SwitchBlock: big.NewInt(0), SwitchBlock: big.NewInt(0),

View file

@ -36,7 +36,7 @@ var TIP2019Block = big.NewInt(1)
var TIPSigning = big.NewInt(3000000) var TIPSigning = big.NewInt(3000000)
var TIPRandomize = big.NewInt(3464000) var TIPRandomize = big.NewInt(3464000)
var TIPV2SwitchBlock = big.NewInt(99999999999) var TIPV2SwitchBlock = big.NewInt(99999999900)
var TIPIncreaseMasternodes = big.NewInt(5000000) // Upgrade MN Count at Block. var TIPIncreaseMasternodes = big.NewInt(5000000) // Upgrade MN Count at Block.
var TIPNoHalvingMNReward = big.NewInt(38383838) // hardfork no halving masternodes reward var TIPNoHalvingMNReward = big.NewInt(38383838) // hardfork no halving masternodes reward
@ -77,6 +77,7 @@ var BaseTopUp = big.NewInt(100)
var BaseRecall = big.NewInt(100) var BaseRecall = big.NewInt(100)
var TIPTRC21Fee = big.NewInt(38383838) var TIPTRC21Fee = big.NewInt(38383838)
var TIPTRC21FeeTestnet = big.NewInt(38383838) var TIPTRC21FeeTestnet = big.NewInt(38383838)
var BlockNumberGas50x = big.NewInt(TIPTRC21Fee.Int64() + 40000000)
var LimitTimeFinality = uint64(30) // limit in 30 block var LimitTimeFinality = uint64(30) // limit in 30 block
var IgnoreSignerCheckBlockArray = map[uint64]bool{ var IgnoreSignerCheckBlockArray = map[uint64]bool{

View file

@ -77,6 +77,7 @@ var BaseTopUp = big.NewInt(100)
var BaseRecall = big.NewInt(100) var BaseRecall = big.NewInt(100)
var TIPTRC21Fee = big.NewInt(13523400) var TIPTRC21Fee = big.NewInt(13523400)
var TIPTRC21FeeTestnet = big.NewInt(225000) var TIPTRC21FeeTestnet = big.NewInt(225000)
var BlockNumberGas50x = big.NewInt(11818181)
var LimitTimeFinality = uint64(30) // limit in 30 block var LimitTimeFinality = uint64(30) // limit in 30 block
var IgnoreSignerCheckBlockArray = map[uint64]bool{ var IgnoreSignerCheckBlockArray = map[uint64]bool{

View file

@ -36,7 +36,7 @@ var TIP2019Block = big.NewInt(1)
var TIPSigning = big.NewInt(3000000) var TIPSigning = big.NewInt(3000000)
var TIPRandomize = big.NewInt(3464000) var TIPRandomize = big.NewInt(3464000)
var TIPV2SwitchBlock = big.NewInt(56000000) var TIPV2SwitchBlock = big.NewInt(56828700) // Target 13rd Nov 2023
var TIPIncreaseMasternodes = big.NewInt(5000000) // Upgrade MN Count at Block. var TIPIncreaseMasternodes = big.NewInt(5000000) // Upgrade MN Count at Block.
var TIPNoHalvingMNReward = big.NewInt(23779191) // hardfork no halving masternodes reward var TIPNoHalvingMNReward = big.NewInt(23779191) // hardfork no halving masternodes reward
@ -77,6 +77,7 @@ var BaseTopUp = big.NewInt(100)
var BaseRecall = big.NewInt(100) var BaseRecall = big.NewInt(100)
var TIPTRC21Fee = big.NewInt(23779191) var TIPTRC21Fee = big.NewInt(23779191)
var TIPTRC21FeeTestnet = big.NewInt(23779191) var TIPTRC21FeeTestnet = big.NewInt(23779191)
var BlockNumberGas50x = big.NewInt(TIPTRC21Fee.Int64() + 40000000)
var LimitTimeFinality = uint64(30) // limit in 30 block var LimitTimeFinality = uint64(30) // limit in 30 block
var IgnoreSignerCheckBlockArray = map[uint64]bool{ var IgnoreSignerCheckBlockArray = map[uint64]bool{

34
common/gas.go Normal file
View file

@ -0,0 +1,34 @@
package common
import "math/big"
var MinGasPrice50x = big.NewInt(12500000000)
var GasPrice50x = big.NewInt(12500000000)
func GetGasFee(blockNumber, gas uint64) *big.Int {
fee := new(big.Int).SetUint64(gas)
if blockNumber >= BlockNumberGas50x.Uint64() {
fee = fee.Mul(fee, GasPrice50x)
} else if blockNumber > TIPTRC21Fee.Uint64() {
fee = fee.Mul(fee, TRC21GasPrice)
}
return fee
}
func GetGasPrice(number *big.Int) *big.Int {
if number == nil || number.Cmp(BlockNumberGas50x) < 0 {
return new(big.Int).Set(TRC21GasPrice)
} else {
return new(big.Int).Set(GasPrice50x)
}
}
func GetMinGasPrice(number *big.Int) *big.Int {
if number == nil || number.Cmp(BlockNumberGas50x) < 0 {
return new(big.Int).Set(MinGasPrice)
} else {
return new(big.Int).Set(MinGasPrice50x)
}
}

View file

@ -73,6 +73,9 @@ func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
func Uint64ToHash(b uint64) Hash { return BytesToHash(new(big.Int).SetUint64(b).Bytes()) } func Uint64ToHash(b uint64) Hash { return BytesToHash(new(big.Int).SetUint64(b).Bytes()) }
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
// IsZero returns if a Hash is empty
func (h Hash) IsZero() bool { return h == Hash{} }
// Get the string representation of the underlying hash // Get the string representation of the underlying hash
func (h Hash) Str() string { return string(h[:]) } func (h Hash) Str() string { return string(h[:]) }
func (h Hash) Bytes() []byte { return h[:] } func (h Hash) Bytes() []byte { return h[:] }
@ -190,6 +193,9 @@ func IsHexAddress(s string) bool {
return len(s) == 2*AddressLength && isHex(s) return len(s) == 2*AddressLength && isHex(s)
} }
// IsZero returns if a address is empty
func (a Address) IsZero() bool { return a == Address{} }
// Get the string representation of the underlying address // Get the string representation of the underlying address
func (a Address) Str() string { return string(a[:]) } func (a Address) Str() string { return string(a[:]) }
func (a Address) Bytes() []byte { return a[:] } func (a Address) Bytes() []byte { return a[:] }

View file

@ -17,6 +17,7 @@
package XDPoS package XDPoS
import ( import (
"fmt"
"math/big" "math/big"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -95,7 +96,11 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database) *XDPoS {
} }
} }
log.Info("xdc config loading", "config", config) if config.V2.SwitchBlock.Uint64()%config.Epoch != 0 {
panic(fmt.Sprintf("v2 switch number is not epoch switch block %d, epoch %d", config.V2.SwitchBlock.Uint64(), config.Epoch))
}
log.Info("xdc config loading", "v2 config", config.V2)
minePeriodCh := make(chan int) minePeriodCh := make(chan int)

View file

@ -164,7 +164,7 @@ func (x *XDPoS_v2) Initial(chain consensus.ChainReader, header *types.Header) er
} }
func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) error { func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) error {
log.Info("[initial] initial v2 related parameters") log.Warn("[initial] initial v2 related parameters")
if x.highestQuorumCert.ProposedBlockInfo.Hash != (common.Hash{}) { // already initialized if x.highestQuorumCert.ProposedBlockInfo.Hash != (common.Hash{}) { // already initialized
log.Info("[initial] Already initialized", "x.highestQuorumCert.ProposedBlockInfo.Hash", x.highestQuorumCert.ProposedBlockInfo.Hash) log.Info("[initial] Already initialized", "x.highestQuorumCert.ProposedBlockInfo.Hash", x.highestQuorumCert.ProposedBlockInfo.Hash)
@ -219,6 +219,12 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er
log.Error("[initial] Error while get masternodes", "error", err) log.Error("[initial] Error while get masternodes", "error", err)
return err return err
} }
if len(masternodes) == 0 {
log.Error("[initial] masternodes are empty", "v2switch", x.config.V2.SwitchBlock.Uint64())
return fmt.Errorf("masternodes are empty v2 switch number: %d", x.config.V2.SwitchBlock.Uint64())
}
snap := newSnapshot(lastGapNum, lastGapHeader.Hash(), masternodes) snap := newSnapshot(lastGapNum, lastGapHeader.Hash(), masternodes)
x.snapshots.Add(snap.Hash, snap) x.snapshots.Add(snap.Hash, snap)
err = storeSnapshot(snap, x.db) err = storeSnapshot(snap, x.db)
@ -229,7 +235,7 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er
} }
// Initial timeout // Initial timeout
log.Info("[initial] miner wait period", "period", x.config.V2.CurrentConfig.MinePeriod) log.Warn("[initial] miner wait period", "period", x.config.V2.CurrentConfig.MinePeriod)
// avoid deadlock // avoid deadlock
go func() { go func() {
x.minePeriodCh <- x.config.V2.CurrentConfig.MinePeriod x.minePeriodCh <- x.config.V2.CurrentConfig.MinePeriod
@ -239,7 +245,7 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er
x.timeoutWorker.Reset(chain) x.timeoutWorker.Reset(chain)
x.isInitilised = true x.isInitilised = true
log.Info("[initial] finish initialisation") log.Warn("[initial] finish initialisation")
return nil return nil
} }

View file

@ -1,6 +1,7 @@
package engine_v2_tests package engine_v2_tests
import ( import (
"encoding/json"
"math/big" "math/big"
"testing" "testing"
@ -124,3 +125,21 @@ func TestSnapshotShouldAlreadyCreatedByUpdateM1(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, uint64(1350), snap.Number) assert.Equal(t, uint64(1350), snap.Number)
} }
func TestInitialWithWrongSwitchNumber(t *testing.T) {
b, err := json.Marshal(params.TestXDPoSMockChainConfig)
assert.Nil(t, err)
configString := string(b)
var config params.ChainConfig
err = json.Unmarshal([]byte(configString), &config)
assert.Nil(t, err)
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 800, &config, nil)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
header := currentBlock.Header()
config.XDPoS.V2.SwitchBlock = big.NewInt(800) // not epoch number
err = adaptor.EngineV2.Initial(blockchain, header)
assert.NotNil(t, err)
}

View file

@ -4,15 +4,16 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"math/big"
"time"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind" "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/contracts/trc21issuer" "github.com/XinFinOrg/XDPoSChain/contracts/trc21issuer"
"github.com/XinFinOrg/XDPoSChain/contracts/trc21issuer/simulation" "github.com/XinFinOrg/XDPoSChain/contracts/trc21issuer/simulation"
"github.com/XinFinOrg/XDPoSChain/ethclient" "github.com/XinFinOrg/XDPoSChain/ethclient"
"log"
"math/big"
"time"
) )
var ( var (
@ -48,11 +49,10 @@ func airDropTokenToAccountNoXDC() {
if err != nil { if err != nil {
log.Fatal("can't transaction's receipt ", err, "hash", tx.Hash().Hex()) log.Fatal("can't transaction's receipt ", err, "hash", tx.Hash().Hex())
} }
fee := big.NewInt(0).SetUint64(hexutil.MustDecodeUint64(receipt["gasUsed"].(string))) gasUsed := hexutil.MustDecodeUint64(receipt["gasUsed"].(string))
if hexutil.MustDecodeUint64(receipt["blockNumber"].(string)) > common.TIPTRC21Fee.Uint64() { blockNumber := hexutil.MustDecodeUint64(receipt["blockNumber"].(string))
fee = fee.Mul(fee, common.TRC21GasPrice) fee := common.GetGasFee(blockNumber, gasUsed)
} fmt.Println("fee", fee.Uint64(), "number", blockNumber)
fmt.Println("fee", fee.Uint64(), "number", hexutil.MustDecodeUint64(receipt["blockNumber"].(string)))
remainFee = big.NewInt(0).Sub(remainFee, fee) remainFee = big.NewInt(0).Sub(remainFee, fee)
//check balance fee //check balance fee
balanceIssuerFee, err := trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr) balanceIssuerFee, err := trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr)
@ -111,11 +111,10 @@ func testTransferTRC21TokenWithAccountNoXDC() {
if err != nil { if err != nil {
log.Fatal("can't transaction's receipt ", err, "hash", tx.Hash().Hex()) log.Fatal("can't transaction's receipt ", err, "hash", tx.Hash().Hex())
} }
fee := big.NewInt(0).SetUint64(hexutil.MustDecodeUint64(receipt["gasUsed"].(string))) gasUsed := hexutil.MustDecodeUint64(receipt["gasUsed"].(string))
if hexutil.MustDecodeUint64(receipt["blockNumber"].(string)) > common.TIPTRC21Fee.Uint64() { blockNumber := hexutil.MustDecodeUint64(receipt["blockNumber"].(string))
fee = fee.Mul(fee, common.TRC21GasPrice) fee := common.GetGasFee(blockNumber, gasUsed)
} fmt.Println("fee", fee.Uint64(), "number", blockNumber)
fmt.Println("fee", fee.Uint64(), "number", hexutil.MustDecodeUint64(receipt["blockNumber"].(string)))
remainFee = big.NewInt(0).Sub(remainFee, fee) remainFee = big.NewInt(0).Sub(remainFee, fee)
//check balance fee //check balance fee
balanceIssuerFee, err := trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr) balanceIssuerFee, err := trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr)
@ -178,11 +177,10 @@ func testTransferTrc21Fail() {
if err != nil { if err != nil {
log.Fatal("can't transaction's receipt ", err, "hash", tx.Hash().Hex()) log.Fatal("can't transaction's receipt ", err, "hash", tx.Hash().Hex())
} }
fee := big.NewInt(0).SetUint64(hexutil.MustDecodeUint64(receipt["gasUsed"].(string))) gasUsed := hexutil.MustDecodeUint64(receipt["gasUsed"].(string))
if hexutil.MustDecodeUint64(receipt["blockNumber"].(string)) > common.TIPTRC21Fee.Uint64() { blockNumber := hexutil.MustDecodeUint64(receipt["blockNumber"].(string))
fee = fee.Mul(fee, common.TRC21GasPrice) fee := common.GetGasFee(blockNumber, gasUsed)
} fmt.Println("fee", fee.Uint64(), "number", blockNumber)
fmt.Println("fee", fee.Uint64(), "number", hexutil.MustDecodeUint64(receipt["blockNumber"].(string)))
remainFee = big.NewInt(0).Sub(remainFee, fee) remainFee = big.NewInt(0).Sub(remainFee, fee)
//check balance fee //check balance fee
balanceIssuerFee, err = trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr) balanceIssuerFee, err = trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr)

View file

@ -1,13 +1,14 @@
package trc21issuer package trc21issuer
import ( import (
"math/big"
"testing"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind" "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends" "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core" "github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/crypto"
"math/big"
"testing"
) )
var ( var (
@ -81,10 +82,7 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("can't transaction's receipt ", err, "hash", tx.Hash()) t.Fatal("can't transaction's receipt ", err, "hash", tx.Hash())
} }
fee := big.NewInt(0).SetUint64(receipt.GasUsed) fee := common.GetGasFee(receipt.Logs[0].BlockNumber, receipt.GasUsed)
if receipt.Logs[0].BlockNumber > common.TIPTRC21Fee.Uint64() {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
remainFee := big.NewInt(0).Sub(minApply, fee) remainFee := big.NewInt(0).Sub(minApply, fee)
// check balance trc21 again // check balance trc21 again
@ -133,10 +131,7 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("can't transaction's receipt ", err, "hash", tx.Hash()) t.Fatal("can't transaction's receipt ", err, "hash", tx.Hash())
} }
fee = big.NewInt(0).SetUint64(receipt.GasUsed) fee = common.GetGasFee(receipt.Logs[0].BlockNumber, receipt.GasUsed)
if receipt.Logs[0].BlockNumber > common.TIPTRC21Fee.Uint64() {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
remainFee = big.NewInt(0).Sub(remainFee, fee) remainFee = big.NewInt(0).Sub(remainFee, fee)
//check balance fee //check balance fee
balanceIssuerFee, err = trc21Issuer.GetTokenCapacity(trc21TokenAddr) balanceIssuerFee, err = trc21Issuer.GetTokenCapacity(trc21TokenAddr)

View file

@ -2554,8 +2554,8 @@ func (bc *BlockChain) UpdateM1() error {
if err != nil { if err != nil {
return err return err
} }
//TODO: smart contract shouldn't return "0x0000000000000000000000000000000000000000" // TODO: smart contract shouldn't return "0x0000000000000000000000000000000000000000"
if candidate.String() != "xdc0000000000000000000000000000000000000000" { if !candidate.IsZero() {
ms = append(ms, utils.Masternode{Address: candidate, Stake: v}) ms = append(ms, utils.Masternode{Address: candidate, Stake: v})
} }
} }

View file

@ -108,10 +108,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b.txs = append(b.txs, tx) b.txs = append(b.txs, tx)
b.receipts = append(b.receipts, receipt) b.receipts = append(b.receipts, receipt)
if tokenFeeUsed { if tokenFeeUsed {
fee := new(big.Int).SetUint64(gas) fee := common.GetGasFee(b.header.Number.Uint64(), gas)
if b.header.Number.Cmp(common.TIPTRC21Fee) > 0 {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
state.UpdateTRC21Fee(b.statedb, map[common.Address]*big.Int{*tx.To(): new(big.Int).Sub(feeCapacity[*tx.To()], new(big.Int).SetUint64(gas))}, fee) state.UpdateTRC21Fee(b.statedb, map[common.Address]*big.Int{*tx.To(): new(big.Int).Sub(feeCapacity[*tx.To()], new(big.Int).SetUint64(gas))}, fee)
} }
} }

View file

@ -431,7 +431,7 @@ func (pool *LendingPool) validateNewLending(cloneStateDb *state.StateDB, cloneLe
return ErrInvalidLendingType return ErrInvalidLendingType
} }
if tx.Side() == lendingstate.Borrowing { if tx.Side() == lendingstate.Borrowing {
if tx.CollateralToken().String() == lendingstate.EmptyAddress || tx.CollateralToken().String() == tx.LendingToken().String() { if tx.CollateralToken().IsZero() || tx.CollateralToken() == tx.LendingToken() {
return ErrInvalidLendingCollateral return ErrInvalidLendingCollateral
} }
validCollateral := false validCollateral := false
@ -541,7 +541,7 @@ func (pool *LendingPool) validateBalance(cloneStateDb *state.StateDB, cloneLendi
// collateralPrice = BTC/USD (eg: 8000 USD) // collateralPrice = BTC/USD (eg: 8000 USD)
// lendTokenXDCPrice: price of lendingToken in XDC quote // lendTokenXDCPrice: price of lendingToken in XDC quote
var lendTokenXDCPrice, collateralPrice, collateralTokenDecimal *big.Int var lendTokenXDCPrice, collateralPrice, collateralTokenDecimal *big.Int
if collateralToken.String() != lendingstate.EmptyAddress { if !collateralToken.IsZero() {
collateralTokenDecimal, err = XDCXServ.GetTokenDecimal(pool.chain, cloneStateDb, collateralToken) collateralTokenDecimal, err = XDCXServ.GetTokenDecimal(pool.chain, cloneStateDb, collateralToken)
if err != nil { if err != nil {
return fmt.Errorf("validateOrder: failed to get collateralTokenDecimal. err: %v", err) return fmt.Errorf("validateOrder: failed to get collateralTokenDecimal. err: %v", err)

View file

@ -93,16 +93,17 @@ func GetCandidates(statedb *StateDB) []common.Address {
slot := slotValidatorMapping["candidates"] slot := slotValidatorMapping["candidates"]
slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) slotHash := common.BigToHash(new(big.Int).SetUint64(slot))
arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), slotHash) arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), slotHash)
keys := []common.Hash{} count := arrLength.Big().Uint64()
for i := uint64(0); i < arrLength.Big().Uint64(); i++ { rets := make([]common.Address, 0, count)
for i := uint64(0); i < count; i++ {
key := GetLocDynamicArrAtElement(slotHash, i, 1) key := GetLocDynamicArrAtElement(slotHash, i, 1)
keys = append(keys, key)
}
rets := []common.Address{}
for _, key := range keys {
ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key) ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key)
rets = append(rets, common.HexToAddress(ret.Hex())) if !ret.IsZero() {
rets = append(rets, common.HexToAddress(ret.Hex()))
}
} }
return rets return rets
} }

View file

@ -120,10 +120,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
receipts = append(receipts, receipt) receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...) allLogs = append(allLogs, receipt.Logs...)
if tokenFeeUsed { if tokenFeeUsed {
fee := new(big.Int).SetUint64(gas) fee := common.GetGasFee(block.Header().Number.Uint64(), gas)
if block.Header().Number.Cmp(common.TIPTRC21Fee) > 0 {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee) balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee)
balanceUpdated[*tx.To()] = balanceFee[*tx.To()] balanceUpdated[*tx.To()] = balanceFee[*tx.To()]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee) totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
@ -201,10 +198,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
receipts[i] = receipt receipts[i] = receipt
allLogs = append(allLogs, receipt.Logs...) allLogs = append(allLogs, receipt.Logs...)
if tokenFeeUsed { if tokenFeeUsed {
fee := new(big.Int).SetUint64(gas) fee := common.GetGasFee(block.Header().Number.Uint64(), gas)
if block.Header().Number.Cmp(common.TIPTRC21Fee) > 0 {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee) balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee)
balanceUpdated[*tx.To()] = balanceFee[*tx.To()] balanceUpdated[*tx.To()] = balanceFee[*tx.To()]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee) totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)

View file

@ -290,7 +290,7 @@ func (l *txList) Forward(threshold uint64) types.Transactions {
// a point in calculating all the costs or if the balance covers all. If the threshold // a point in calculating all the costs or if the balance covers all. If the threshold
// is lower than the costgas cap, the caps will be reset to a new high after removing // is lower than the costgas cap, the caps will be reset to a new high after removing
// the newly invalidated transactions. // the newly invalidated transactions.
func (l *txList) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[common.Address]*big.Int) (types.Transactions, types.Transactions) { func (l *txList) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[common.Address]*big.Int, number *big.Int) (types.Transactions, types.Transactions) {
// If all transactions are below the threshold, short circuit // If all transactions are below the threshold, short circuit
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit { if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
return nil, nil return nil, nil
@ -303,7 +303,7 @@ func (l *txList) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[co
maximum := costLimit maximum := costLimit
if tx.To() != nil { if tx.To() != nil {
if feeCapacity, ok := trc21Issuers[*tx.To()]; ok { if feeCapacity, ok := trc21Issuers[*tx.To()]; ok {
return new(big.Int).Add(costLimit, feeCapacity).Cmp(tx.TRC21Cost()) < 0 || tx.Gas() > gasLimit return new(big.Int).Add(costLimit, feeCapacity).Cmp(tx.TxCost(number)) < 0 || tx.Gas() > gasLimit
} }
} }
return tx.Cost().Cmp(maximum) > 0 || tx.Gas() > gasLimit return tx.Cost().Cmp(maximum) > 0 || tx.Gas() > gasLimit

View file

@ -632,7 +632,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
// cost == V + GP * GL // cost == V + GP * GL
balance := pool.currentState.GetBalance(from) balance := pool.currentState.GetBalance(from)
cost := tx.Cost() cost := tx.Cost()
minGasPrice := common.MinGasPrice var number *big.Int = nil
if pool.chain.CurrentHeader() != nil {
number = pool.chain.CurrentHeader().Number
}
minGasPrice := common.GetMinGasPrice(number)
feeCapacity := big.NewInt(0) feeCapacity := big.NewInt(0)
if tx.To() != nil { if tx.To() != nil {
@ -641,8 +645,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if !state.ValidateTRC21Tx(pool.pendingState.StateDB, from, *tx.To(), tx.Data()) { if !state.ValidateTRC21Tx(pool.pendingState.StateDB, from, *tx.To(), tx.Data()) {
return ErrInsufficientFunds return ErrInsufficientFunds
} }
cost = tx.TRC21Cost() cost = tx.TxCost(number)
minGasPrice = common.TRC21GasPrice
} }
} }
if new(big.Int).Add(balance, feeCapacity).Cmp(cost) < 0 { if new(big.Int).Add(balance, feeCapacity).Cmp(cost) < 0 {
@ -1066,7 +1069,11 @@ func (pool *TxPool) promoteExecutables(accounts []common.Address) {
pool.priced.Removed() pool.priced.Removed()
} }
// Drop all transactions that are too costly (low balance or out of gas) // Drop all transactions that are too costly (low balance or out of gas)
drops, _ := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas, pool.trc21FeeCapacity) var number *big.Int = nil
if pool.chain.CurrentHeader() != nil {
number = pool.chain.CurrentHeader().Number
}
drops, _ := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas, pool.trc21FeeCapacity, number)
for _, tx := range drops { for _, tx := range drops {
hash := tx.Hash() hash := tx.Hash()
log.Trace("Removed unpayable queued transaction", "hash", hash) log.Trace("Removed unpayable queued transaction", "hash", hash)
@ -1224,7 +1231,11 @@ func (pool *TxPool) demoteUnexecutables() {
pool.priced.Removed() pool.priced.Removed()
} }
// Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later
drops, invalids := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas, pool.trc21FeeCapacity) var number *big.Int = nil
if pool.chain.CurrentHeader() != nil {
number = pool.chain.CurrentHeader().Number
}
drops, invalids := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas, pool.trc21FeeCapacity, number)
for _, tx := range drops { for _, tx := range drops {
hash := tx.Hash() hash := tx.Hash()
log.Trace("Removed unpayable pending transaction", "hash", hash) log.Trace("Removed unpayable pending transaction", "hash", hash)

View file

@ -262,7 +262,9 @@ func (tx *Transaction) AsMessage(s Signer, balanceFee *big.Int, number *big.Int)
var err error var err error
msg.from, err = Sender(s, tx) msg.from, err = Sender(s, tx)
if balanceFee != nil { if balanceFee != nil {
if number.Cmp(common.TIPTRC21Fee) > 0 { if number.Cmp(common.BlockNumberGas50x) >= 0 {
msg.gasPrice = common.GasPrice50x
} else if number.Cmp(common.TIPTRC21Fee) > 0 {
msg.gasPrice = common.TRC21GasPrice msg.gasPrice = common.TRC21GasPrice
} else { } else {
msg.gasPrice = common.TRC21GasPriceBefore msg.gasPrice = common.TRC21GasPriceBefore
@ -291,8 +293,8 @@ func (tx *Transaction) Cost() *big.Int {
} }
// Cost returns amount + gasprice * gaslimit. // Cost returns amount + gasprice * gaslimit.
func (tx *Transaction) TRC21Cost() *big.Int { func (tx *Transaction) TxCost(number *big.Int) *big.Int {
total := new(big.Int).Mul(common.TRC21GasPrice, new(big.Int).SetUint64(tx.data.GasLimit)) total := new(big.Int).Mul(common.GetGasPrice(number), new(big.Int).SetUint64(tx.data.GasLimit))
total.Add(total, tx.data.Amount) total.Add(total, tx.data.Amount)
return total return total
} }
@ -700,9 +702,9 @@ type Message struct {
balanceTokenFee *big.Int balanceTokenFee *big.Int
} }
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool, balanceTokenFee *big.Int) Message { func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool, balanceTokenFee *big.Int, number *big.Int) Message {
if balanceTokenFee != nil { if balanceTokenFee != nil {
gasPrice = common.TRC21GasPrice gasPrice = common.GetGasPrice(number)
} }
return Message{ return Message{
from: from, from: from,

View file

@ -706,10 +706,7 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
} }
if tokenFeeUsed { if tokenFeeUsed {
fee := new(big.Int).SetUint64(gas) fee := common.GetGasFee(block.Header().Number.Uint64(), gas)
if block.Header().Number.Cmp(common.TIPTRC21Fee) > 0 {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
feeCapacity[*tx.To()] = new(big.Int).Sub(feeCapacity[*tx.To()], fee) feeCapacity[*tx.To()] = new(big.Int).Sub(feeCapacity[*tx.To()], fee)
balanceUpdated[*tx.To()] = feeCapacity[*tx.To()] balanceUpdated[*tx.To()] = feeCapacity[*tx.To()]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee) totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)

View file

@ -141,7 +141,7 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
} }
// Check gas price min. // Check gas price min.
minGasPrice := common.MinGasPrice minGasPrice := common.GetMinGasPrice(head.Number)
if price.Cmp(minGasPrice) < 0 { if price.Cmp(minGasPrice) < 0 {
price = new(big.Int).Set(minGasPrice) price = new(big.Int).Set(minGasPrice)
} }

View file

@ -238,9 +238,7 @@ func AttachConsensusV1Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
if err != nil { if err != nil {
return nil, err return nil, err
} }
if address.String() != "xdc0000000000000000000000000000000000000000" { candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
}
} }
// sort candidates by stake descending // sort candidates by stake descending
sort.Slice(candidates, func(i, j int) bool { sort.Slice(candidates, func(i, j int) bool {

View file

@ -754,11 +754,10 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
return result, err return result, err
} }
candidatesAddresses := state.GetCandidates(statedb) candidatesAddresses := state.GetCandidates(statedb)
candidates = make([]utils.Masternode, 0, len(candidatesAddresses))
for _, address := range candidatesAddresses { for _, address := range candidatesAddresses {
v := state.GetCandidateCap(statedb, address) v := state.GetCandidateCap(statedb, address)
if address.String() != "xdc0000000000000000000000000000000000000000" { candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
}
} }
} }
if err != nil || len(candidates) == 0 { if err != nil || len(candidates) == 0 {
@ -766,6 +765,7 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
result[fieldSuccess] = false result[fieldSuccess] = false
return result, err return result, err
} }
var maxMasternodes int var maxMasternodes int
if s.b.ChainConfig().IsTIPIncreaseMasternodes(block.Number()) { if s.b.ChainConfig().IsTIPIncreaseMasternodes(block.Number()) {
maxMasternodes = common.MaxMasternodesV2 maxMasternodes = common.MaxMasternodesV2
@ -773,24 +773,19 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
maxMasternodes = common.MaxMasternodes maxMasternodes = common.MaxMasternodes
} }
isTopCandidate := false // check penalties from checkpoint headers and modify status of a node to SLASHED if it's in top maxMasternodes candidates.
// check penalties from checkpoint headers and modify status of a node to SLASHED if it's in top 150 candidates // if it's SLASHED but it's out of top maxMasternodes, the status should be still PROPOSED.
// if it's SLASHED but it's out of top 150, the status should be still PROPOSED isCandidate := false
for i := 0; i < len(candidates); i++ { for i := 0; i < len(candidates); i++ {
if coinbaseAddress == candidates[i].Address { if coinbaseAddress == candidates[i].Address {
if i < maxMasternodes { isCandidate = true
isTopCandidate = true
}
result[fieldStatus] = statusProposed result[fieldStatus] = statusProposed
result[fieldCapacity] = candidates[i].Stake result[fieldCapacity] = candidates[i].Stake
break break
} }
} }
if !isTopCandidate {
return result, nil
}
// Second, Find candidates that have masternode status // Get masternode list
if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok { if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok {
masternodes = engine.GetMasternodesFromCheckpointHeader(header) masternodes = engine.GetMasternodesFromCheckpointHeader(header)
if len(masternodes) == 0 { if len(masternodes) == 0 {
@ -801,15 +796,30 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
} else { } else {
log.Error("Undefined XDPoS consensus engine") log.Error("Undefined XDPoS consensus engine")
} }
// Set masternode status
// Set to statusMasternode if it is masternode
for _, masternode := range masternodes { for _, masternode := range masternodes {
if coinbaseAddress == masternode { if coinbaseAddress == masternode {
result[fieldStatus] = statusMasternode result[fieldStatus] = statusMasternode
if !isCandidate {
result[fieldCapacity] = -1
log.Warn("Find non-candidate masternode", "masternode", masternode.String(), "checkpointNumber", checkpointNumber, "epoch", epoch, "epochNumber", epochNumber)
}
return result, nil return result, nil
} }
} }
// Third, Get penalties list if !isCandidate || len(masternodes) >= maxMasternodes {
return result, nil
}
if len(candidates) > maxMasternodes {
sort.Slice(candidates, func(i, j int) bool {
return candidates[i].Stake.Cmp(candidates[j].Stake) > 0
})
}
// Get penalties list
penalties = append(penalties, header.Penalties...) penalties = append(penalties, header.Penalties...)
// check last 5 epochs to find penalize masternodes // check last 5 epochs to find penalize masternodes
for i := 1; i <= common.LimitPenaltyEpoch; i++ { for i := 1; i <= common.LimitPenaltyEpoch; i++ {
@ -827,12 +837,22 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
penaltyList = common.ExtractAddressFromBytes(penalties) penaltyList = common.ExtractAddressFromBytes(penalties)
// map slashing status // map slashing status
for _, pen := range penaltyList { total := len(masternodes)
if coinbaseAddress == pen { for _, candidate := range candidates {
result[fieldStatus] = statusSlashed for _, pen := range penaltyList {
return result, nil if candidate.Address == pen {
if coinbaseAddress == pen {
result[fieldStatus] = statusSlashed
return result, nil
}
total++
if total >= maxMasternodes {
return result, nil
}
}
} }
} }
return result, nil return result, nil
} }
@ -853,7 +873,6 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
fieldSuccess: true, fieldSuccess: true,
} }
epochConfig := s.b.ChainConfig().XDPoS.Epoch epochConfig := s.b.ChainConfig().XDPoS.Epoch
candidatesStatusMap := map[string]map[string]interface{}{}
checkpointNumber, epochNumber = s.GetPreviousCheckpointFromEpoch(ctx, epoch) checkpointNumber, epochNumber = s.GetPreviousCheckpointFromEpoch(ctx, epoch)
result[fieldEpoch] = epochNumber.Int64() result[fieldEpoch] = epochNumber.Int64()
@ -880,11 +899,10 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
return result, err return result, err
} }
candidatesAddresses := state.GetCandidates(statedb) candidatesAddresses := state.GetCandidates(statedb)
candidates = make([]utils.Masternode, 0, len(candidatesAddresses))
for _, address := range candidatesAddresses { for _, address := range candidatesAddresses {
v := state.GetCandidateCap(statedb, address) v := state.GetCandidateCap(statedb, address)
if address.String() != "xdc0000000000000000000000000000000000000000" { candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
}
} }
} }
@ -893,15 +911,8 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
result[fieldSuccess] = false result[fieldSuccess] = false
return result, err return result, err
} }
// First, set all candidate to propose
for _, candidate := range candidates {
candidatesStatusMap[candidate.Address.String()] = map[string]interface{}{
fieldStatus: statusProposed,
fieldCapacity: candidate.Stake,
}
}
// Second, Find candidates that have masternode status // Find candidates that have masternode status
if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok { if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok {
masternodes = engine.GetMasternodesFromCheckpointHeader(header) masternodes = engine.GetMasternodesFromCheckpointHeader(header)
if len(masternodes) == 0 { if len(masternodes) == 0 {
@ -912,14 +923,49 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
} else { } else {
log.Error("Undefined XDPoS consensus engine") log.Error("Undefined XDPoS consensus engine")
} }
// Set masternode status
for _, masternode := range masternodes { // Set all candidate to statusProposed
if candidatesStatusMap[masternode.String()] != nil { candidatesStatusMap := make(map[string]map[string]interface{}, len(candidates))
candidatesStatusMap[masternode.String()][fieldStatus] = statusMasternode for _, candidate := range candidates {
candidatesStatusMap[candidate.Address.String()] = map[string]interface{}{
fieldStatus: statusProposed,
fieldCapacity: candidate.Stake,
} }
} }
// Third, Get penalties list // Set masternodes to statusMasternode
for _, masternode := range masternodes {
key := masternode.String()
if candidatesStatusMap[key] != nil {
candidatesStatusMap[key][fieldStatus] = statusMasternode
} else {
candidatesStatusMap[key] = map[string]interface{}{
fieldStatus: statusMasternode,
fieldCapacity: -1,
}
log.Warn("Masternode is not candidate", "masternode", key, "checkpointNumber", checkpointNumber, "epoch", epoch, "epochNumber", epochNumber)
}
}
var maxMasternodes int
if s.b.ChainConfig().IsTIPIncreaseMasternodes(block.Number()) {
maxMasternodes = common.MaxMasternodesV2
} else {
maxMasternodes = common.MaxMasternodes
}
if len(masternodes) >= maxMasternodes {
result[fieldCandidates] = candidatesStatusMap
return result, nil
}
if len(candidates) > maxMasternodes {
sort.Slice(candidates, func(i, j int) bool {
return candidates[i].Stake.Cmp(candidates[j].Stake) > 0
})
}
// Get penalties list
penalties = append(penalties, header.Penalties...) penalties = append(penalties, header.Penalties...)
// check last 5 epochs to find penalize masternodes // check last 5 epochs to find penalize masternodes
for i := 1; i <= common.LimitPenaltyEpoch; i++ { for i := 1; i <= common.LimitPenaltyEpoch; i++ {
@ -941,20 +987,19 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
} }
penaltyList = common.ExtractAddressFromBytes(penalties) penaltyList = common.ExtractAddressFromBytes(penalties)
var topCandidates []utils.Masternode // check penalties from checkpoint headers and modify status of a node to SLASHED if it's in top maxMasternodes candidates.
if len(candidates) > common.MaxMasternodes { // if it's SLASHED but it's out of top maxMasternodes, the status should be still PROPOSED.
topCandidates = candidates[:common.MaxMasternodes] total := len(masternodes)
} else { for _, candidate := range candidates {
topCandidates = candidates for _, pen := range penaltyList {
} if candidate.Address == pen {
// check penalties from checkpoint headers and modify status of a node to SLASHED if it's in top 150 candidates
// if it's SLASHED but it's out of top 150, the status should be still PROPOSED
for _, pen := range penaltyList {
for _, candidate := range topCandidates {
if candidate.Address == pen && candidatesStatusMap[pen.String()] != nil {
candidatesStatusMap[pen.String()][fieldStatus] = statusSlashed candidatesStatusMap[pen.String()][fieldStatus] = statusSlashed
total++
if total >= maxMasternodes {
result[fieldCandidates] = candidatesStatusMap
return result, nil
}
} }
penalties = append(penalties, block.Penalties()...)
} }
} }
@ -966,28 +1011,23 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
// GetPreviousCheckpointFromEpoch returns header of the previous checkpoint // GetPreviousCheckpointFromEpoch returns header of the previous checkpoint
func (s *PublicBlockChainAPI) GetPreviousCheckpointFromEpoch(ctx context.Context, epochNum rpc.EpochNumber) (rpc.BlockNumber, rpc.EpochNumber) { func (s *PublicBlockChainAPI) GetPreviousCheckpointFromEpoch(ctx context.Context, epochNum rpc.EpochNumber) (rpc.BlockNumber, rpc.EpochNumber) {
var checkpointNumber uint64 var checkpointNumber uint64
epoch := s.b.ChainConfig().XDPoS.Epoch
if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok { if epochNum == rpc.LatestEpochNumber {
currentCheckpointNumber, epochNumber, err := engine.GetCurrentEpochSwitchBlock(s.chainReader, s.b.CurrentBlock().Number()) blockNumer := s.b.CurrentBlock().Number().Uint64()
if err != nil { diff := blockNumer % epoch
log.Error("[GetPreviousCheckpointFromEpoch] Error while trying to get current epoch switch block information", "Block", s.b.CurrentBlock(), "Error", err) // checkpoint number
checkpointNumber = blockNumer - diff
epochNum = rpc.EpochNumber(checkpointNumber / epoch)
if diff > 0 {
epochNum += 1
} }
if epochNum == rpc.LatestEpochNumber { } else if epochNum < 2 {
checkpointNumber = currentCheckpointNumber checkpointNumber = 0
epochNum = rpc.EpochNumber(epochNumber)
} else if epochNum < 2 {
checkpointNumber = 0
} else {
blockNumberBeforeCurrentEpochSwitch := currentCheckpointNumber - 1
checkpointNumber, _, err = engine.GetCurrentEpochSwitchBlock(s.chainReader, big.NewInt(int64(blockNumberBeforeCurrentEpochSwitch)))
if err != nil {
log.Error("[GetPreviousCheckpointFromEpoch] Error while trying to get last epoch switch block information", "Number", blockNumberBeforeCurrentEpochSwitch, "Error", err)
}
}
return rpc.BlockNumber(checkpointNumber), epochNum
} else { } else {
panic("[GetPreviousCheckpointFromEpoch] Error while trying to get XDPoS consensus engine") checkpointNumber = epoch * (uint64(epochNum) - 1)
} }
return rpc.BlockNumber(checkpointNumber), epochNum
} }
// getCandidatesFromSmartContract returns all candidates with their capacities at the current time // getCandidatesFromSmartContract returns all candidates with their capacities at the current time
@ -1009,23 +1049,19 @@ func (s *PublicBlockChainAPI) getCandidatesFromSmartContract() ([]utils.Masterno
return []utils.Masternode{}, err return []utils.Masternode{}, err
} }
var candidatesWithStakeInfo []utils.Masternode candidatesWithStakeInfo := make([]utils.Masternode, 0, len(candidates))
for _, candidate := range candidates { for _, candidate := range candidates {
v, err := validator.GetCandidateCap(opts, candidate) if !candidate.IsZero() {
if err != nil { v, err := validator.GetCandidateCap(opts, candidate)
return []utils.Masternode{}, err if err != nil {
} return []utils.Masternode{}, err
if candidate.String() != "xdc0000000000000000000000000000000000000000" { }
candidatesWithStakeInfo = append(candidatesWithStakeInfo, utils.Masternode{Address: candidate, Stake: v}) candidatesWithStakeInfo = append(candidatesWithStakeInfo, utils.Masternode{Address: candidate, Stake: v})
} }
if len(candidatesWithStakeInfo) > 0 {
sort.Slice(candidatesWithStakeInfo, func(i, j int) bool {
return candidatesWithStakeInfo[i].Stake.Cmp(candidatesWithStakeInfo[j].Stake) >= 0
})
}
} }
return candidatesWithStakeInfo, nil return candidatesWithStakeInfo, nil
} }
@ -1066,7 +1102,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
balanceTokenFee := big.NewInt(0).SetUint64(gas) balanceTokenFee := big.NewInt(0).SetUint64(gas)
balanceTokenFee = balanceTokenFee.Mul(balanceTokenFee, gasPrice) balanceTokenFee = balanceTokenFee.Mul(balanceTokenFee, gasPrice)
// Create new call message // Create new call message
msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false, balanceTokenFee) msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false, balanceTokenFee, header.Number)
// Setup context so it may be cancelled the call has completed // Setup context so it may be cancelled the call has completed
// or, in case of unmetered gas, setup a context with a timeout. // or, in case of unmetered gas, setup a context with a timeout.

View file

@ -133,7 +133,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
if value, ok := feeCapacity[testContractAddr]; ok { if value, ok := feeCapacity[testContractAddr]; ok {
balanceTokenFee = value balanceTokenFee = value
} }
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, balanceTokenFee)} msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, balanceTokenFee, header.Number)}
context := core.NewEVMContext(msg, header, bc, nil) context := core.NewEVMContext(msg, header, bc, nil)
vmenv := vm.NewEVM(context, statedb, nil, config, vm.Config{}) vmenv := vm.NewEVM(context, statedb, nil, config, vm.Config{})
@ -153,7 +153,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
if value, ok := feeCapacity[testContractAddr]; ok { if value, ok := feeCapacity[testContractAddr]; ok {
balanceTokenFee = value balanceTokenFee = value
} }
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, balanceTokenFee)} msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false, balanceTokenFee, header.Number)}
context := core.NewEVMContext(msg, header, lc, nil) context := core.NewEVMContext(msg, header, lc, nil)
vmenv := vm.NewEVM(context, statedb, nil, config, vm.Config{}) vmenv := vm.NewEVM(context, statedb, nil, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64) gp := new(core.GasPool).AddGas(math.MaxUint64)

View file

@ -183,7 +183,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
if value, ok := feeCapacity[testContractAddr]; ok { if value, ok := feeCapacity[testContractAddr]; ok {
balanceTokenFee = value balanceTokenFee = value
} }
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false, balanceTokenFee)} msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false, balanceTokenFee, header.Number)}
context := core.NewEVMContext(msg, header, chain, nil) context := core.NewEVMContext(msg, header, chain, nil)
vmenv := vm.NewEVM(context, st, nil, config, vm.Config{}) vmenv := vm.NewEVM(context, st, nil, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64) gp := new(core.GasPool).AddGas(math.MaxUint64)

View file

@ -931,10 +931,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
log.Debug("Add Special Transaction failed, account skipped", "hash", tx.Hash(), "sender", from, "nonce", tx.Nonce(), "to", tx.To(), "err", err) log.Debug("Add Special Transaction failed, account skipped", "hash", tx.Hash(), "sender", from, "nonce", tx.Nonce(), "to", tx.To(), "err", err)
} }
if tokenFeeUsed { if tokenFeeUsed {
fee := new(big.Int).SetUint64(gas) fee := common.GetGasFee(env.header.Number.Uint64(), gas)
if env.header.Number.Cmp(common.TIPTRC21Fee) > 0 {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee) balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee)
balanceUpdated[*tx.To()] = balanceFee[*tx.To()] balanceUpdated[*tx.To()] = balanceFee[*tx.To()]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee) totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
@ -1049,10 +1046,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Ad
txs.Shift() txs.Shift()
} }
if tokenFeeUsed { if tokenFeeUsed {
fee := new(big.Int).SetUint64(gas) fee := common.GetGasFee(env.header.Number.Uint64(), gas)
if env.header.Number.Cmp(common.TIPTRC21Fee) > 0 {
fee = fee.Mul(fee, common.TRC21GasPrice)
}
balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee) balanceFee[*tx.To()] = new(big.Int).Sub(balanceFee[*tx.To()], fee)
balanceUpdated[*tx.To()] = balanceFee[*tx.To()] balanceUpdated[*tx.To()] = balanceFee[*tx.To()]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee) totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)

View file

@ -45,7 +45,7 @@ var (
CertThreshold: 73, // based on masternode is 108 CertThreshold: 73, // based on masternode is 108
TimeoutSyncThreshold: 3, TimeoutSyncThreshold: 3,
TimeoutPeriod: 60, TimeoutPeriod: 60,
MinePeriod: 10, MinePeriod: 2,
}, },
} }
@ -197,7 +197,7 @@ var (
ConstantinopleBlock: nil, ConstantinopleBlock: nil,
XDPoS: &XDPoSConfig{ XDPoS: &XDPoSConfig{
Period: 15, Period: 15,
Epoch: 30000, Epoch: 900,
V2: &V2{ V2: &V2{
SwitchBlock: big.NewInt(9999999999), SwitchBlock: big.NewInt(9999999999),
CurrentConfig: MainnetV2Configs[0], CurrentConfig: MainnetV2Configs[0],
@ -218,8 +218,8 @@ var (
// //
// This configuration is intentionally not using keyed fields to force anyone // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // adding flags to the config to also have to set these fields.
AllXDPoSProtocolChanges = &ChainConfig{big.NewInt(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}} 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: 900}}
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil} AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 900}, nil}
// XDPoS config with v2 engine after block 901 // XDPoS config with v2 engine after block 901
TestXDPoSMockChainConfig = &ChainConfig{ TestXDPoSMockChainConfig = &ChainConfig{
@ -337,10 +337,6 @@ func (c *XDPoSConfig) String() string {
} }
func (c *XDPoSConfig) BlockConsensusVersion(num *big.Int, extraByte []byte, extraCheck bool) string { func (c *XDPoSConfig) BlockConsensusVersion(num *big.Int, extraByte []byte, extraCheck bool) string {
if extraCheck && (len(extraByte) == 0 || extraByte[0] != 2) {
return ConsensusEngineVersion1
}
if c.V2 != nil && c.V2.SwitchBlock != nil && num.Cmp(c.V2.SwitchBlock) > 0 { if c.V2 != nil && c.V2.SwitchBlock != nil && num.Cmp(c.V2.SwitchBlock) > 0 {
return ConsensusEngineVersion2 return ConsensusEngineVersion2
} }
@ -361,7 +357,7 @@ func (v *V2) UpdateConfig(round uint64) {
} }
} }
// update to current config // update to current config
log.Info("[updateV2Config] Update config", "index", index, "round", round, "SwitchRound", v.AllConfigs[index].SwitchRound) log.Warn("[updateV2Config] Update config", "index", index, "round", round, "SwitchRound", v.AllConfigs[index].SwitchRound)
v.CurrentConfig = v.AllConfigs[index] v.CurrentConfig = v.AllConfigs[index]
} }

View file

@ -21,10 +21,10 @@ import (
) )
const ( const (
VersionMajor = 1 // Major version component of the current release VersionMajor = 1 // Major version component of the current release
VersionMinor = 4 // Minor version component of the current release VersionMinor = 4 // Minor version component of the current release
VersionPatch = 9 // Patch version component of the current release VersionPatch = 10 // Patch version component of the current release
VersionMeta = "beta" // Version metadata to append to the version string VersionMeta = "beta1" // Version metadata to append to the version string
) )
// Version holds the textual version string. // Version holds the textual version string.

View file

@ -131,7 +131,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
statedb := MakePreState(db, t.json.Pre) statedb := MakePreState(db, t.json.Pre)
post := t.json.Post[subtest.Fork][subtest.Index] post := t.json.Post[subtest.Fork][subtest.Index]
msg, err := t.json.Tx.toMessage(post) msg, err := t.json.Tx.toMessage(post, block.Number())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -190,7 +190,7 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
} }
} }
func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) { func (tx *stTransaction) toMessage(ps stPostState, number *big.Int) (core.Message, error) {
// Derive sender from private key if present. // Derive sender from private key if present.
var from common.Address var from common.Address
if len(tx.PrivateKey) > 0 { if len(tx.PrivateKey) > 0 {
@ -235,7 +235,7 @@ func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid tx data %q", dataHex) return nil, fmt.Errorf("invalid tx data %q", dataHex)
} }
msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, data, true, nil) msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, data, true, nil, number)
return msg, nil return msg, nil
} }