diff --git a/XDCx/token.go b/XDCx/token.go
index 6596596930fa..dcee2ae36fbc 100644
--- a/XDCx/token.go
+++ b/XDCx/token.go
@@ -52,8 +52,9 @@ func (XDCx *XDCX) GetTokenDecimal(chain consensus.ChainContext, statedb *state.S
return common.BasePrice, nil
}
var decimals uint8
+ relayerSMC := statedb.RelayerRegistrationSMC()
defer func() {
- log.Debug("GetTokenDecimal from ", "relayerSMC", common.RelayerRegistrationSMC, "tokenAddr", tokenAddr.Hex(), "decimals", decimals)
+ log.Debug("GetTokenDecimal from ", "relayerSMC", relayerSMC, "tokenAddr", tokenAddr.Hex(), "decimals", decimals)
}()
contractABI, err := GetTokenAbi()
if err != nil {
diff --git a/XDCx/tradingstate/orderitem.go b/XDCx/tradingstate/orderitem.go
index b87dfecfeca4..1ed13a863f6a 100644
--- a/XDCx/tradingstate/orderitem.go
+++ b/XDCx/tradingstate/orderitem.go
@@ -310,7 +310,7 @@ func IsValidRelayer(statedb *state.StateDB, address common.Address) bool {
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locRelayerState, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance := statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance := statedb.GetState(statedb.RelayerRegistrationSMC(), locHashDeposit).Big()
if balance.Cmp(new(big.Int).Mul(common.BasePrice, common.RelayerLockedFund)) <= 0 {
log.Debug("Relayer is not in relayer list", "relayer", address, "balance", balance)
return false
diff --git a/XDCx/tradingstate/relayer_state.go b/XDCx/tradingstate/relayer_state.go
index 436ff2a5063e..a2426de8bee5 100644
--- a/XDCx/tradingstate/relayer_state.go
+++ b/XDCx/tradingstate/relayer_state.go
@@ -20,12 +20,16 @@ func GetLocMappingAtKey(key common.Hash, slot uint64) *big.Int {
return ret
}
+func relayerRegistrationSMC(statedb *state.StateDB) common.Address {
+ return statedb.RelayerRegistrationSMC()
+}
+
func GetExRelayerFee(relayer common.Address, statedb *state.StateDB) *big.Int {
slot := RelayerMappingSlot["RELAYER_LIST"]
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_fee"])
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash).Big()
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash).Big()
}
func GetRelayerOwner(relayer common.Address, statedb *state.StateDB) common.Address {
@@ -34,7 +38,7 @@ func GetRelayerOwner(relayer common.Address, statedb *state.StateDB) common.Addr
log.Debug("GetRelayerOwner", "relayer", relayer.Hex(), "slot", slot, "locBig", locBig)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_owner"])
locHash := common.BigToHash(locBig)
- return common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, locHash).Bytes())
+ return common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), locHash).Bytes())
}
// return true if relayer request to resign and have not withdraw locked fund
@@ -42,7 +46,7 @@ func IsResignedRelayer(relayer common.Address, statedb *state.StateDB) bool {
slot := RelayerMappingSlot["RESIGN_REQUESTS"]
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash) != (common.Hash{})
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash) != (common.Hash{})
}
func GetBaseTokenLength(relayer common.Address, statedb *state.StateDB) uint64 {
@@ -50,7 +54,7 @@ func GetBaseTokenLength(relayer common.Address, statedb *state.StateDB) uint64 {
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_fromTokens"])
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash).Big().Uint64()
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash).Big().Uint64()
}
func GetBaseTokenAtIndex(relayer common.Address, statedb *state.StateDB, index uint64) common.Address {
@@ -59,7 +63,7 @@ func GetBaseTokenAtIndex(relayer common.Address, statedb *state.StateDB, index u
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_fromTokens"])
locHash := common.BigToHash(locBig)
loc := state.GetLocDynamicArrAtElement(locHash, index, 1)
- return common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, loc).Bytes())
+ return common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), loc).Bytes())
}
func GetQuoteTokenLength(relayer common.Address, statedb *state.StateDB) uint64 {
@@ -67,7 +71,7 @@ func GetQuoteTokenLength(relayer common.Address, statedb *state.StateDB) uint64
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_toTokens"])
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash).Big().Uint64()
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash).Big().Uint64()
}
func GetQuoteTokenAtIndex(relayer common.Address, statedb *state.StateDB, index uint64) common.Address {
@@ -76,13 +80,13 @@ func GetQuoteTokenAtIndex(relayer common.Address, statedb *state.StateDB, index
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_toTokens"])
locHash := common.BigToHash(locBig)
loc := state.GetLocDynamicArrAtElement(locHash, index, 1)
- return common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, loc).Bytes())
+ return common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), loc).Bytes())
}
func GetRelayerCount(statedb *state.StateDB) uint64 {
slot := RelayerMappingSlot["RelayerCount"]
slotHash := common.BigToHash(new(big.Int).SetUint64(slot))
- valueHash := statedb.GetState(common.RelayerRegistrationSMC, slotHash)
+ valueHash := statedb.GetState(relayerRegistrationSMC(statedb), slotHash)
return new(big.Int).SetBytes(valueHash.Bytes()).Uint64()
}
@@ -91,7 +95,7 @@ func GetAllCoinbases(statedb *state.StateDB) []common.Address {
slot := RelayerMappingSlot["RELAYER_COINBASES"]
coinbases := []common.Address{}
for i := uint64(0); i < relayerCount; i++ {
- valueHash := statedb.GetState(common.RelayerRegistrationSMC, common.BytesToHash(state.GetLocMappingAtKey(common.BigToHash(big.NewInt(int64(i))), slot).Bytes()))
+ valueHash := statedb.GetState(relayerRegistrationSMC(statedb), common.BytesToHash(state.GetLocMappingAtKey(common.BigToHash(big.NewInt(int64(i))), slot).Bytes()))
coinbases = append(coinbases, common.BytesToAddress(valueHash.Bytes()))
}
return coinbases
@@ -103,21 +107,21 @@ func GetAllTradingPairs(statedb *state.StateDB) (map[common.Hash]bool, error) {
for _, coinbase := range coinbases {
locBig := GetLocMappingAtKey(coinbase.Hash(), slot)
fromTokenSlot := new(big.Int).Add(locBig, RelayerStructMappingSlot["_fromTokens"])
- fromTokenLength := statedb.GetState(common.RelayerRegistrationSMC, common.BigToHash(fromTokenSlot)).Big().Uint64()
+ fromTokenLength := statedb.GetState(relayerRegistrationSMC(statedb), common.BigToHash(fromTokenSlot)).Big().Uint64()
toTokenSlot := new(big.Int).Add(locBig, RelayerStructMappingSlot["_toTokens"])
- toTokenLength := statedb.GetState(common.RelayerRegistrationSMC, common.BigToHash(toTokenSlot)).Big().Uint64()
+ toTokenLength := statedb.GetState(relayerRegistrationSMC(statedb), common.BigToHash(toTokenSlot)).Big().Uint64()
if toTokenLength != fromTokenLength {
return map[common.Hash]bool{}, fmt.Errorf("invalid length from token & to token: from :%d , to :%d ", fromTokenLength, toTokenLength)
}
fromTokens := []common.Address{}
fromTokenSlotHash := common.BytesToHash(fromTokenSlot.Bytes())
for i := uint64(0); i < fromTokenLength; i++ {
- fromToken := common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, state.GetLocDynamicArrAtElement(fromTokenSlotHash, i, uint64(1))).Bytes())
+ fromToken := common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), state.GetLocDynamicArrAtElement(fromTokenSlotHash, i, uint64(1))).Bytes())
fromTokens = append(fromTokens, fromToken)
}
toTokenSlotHash := common.BytesToHash(toTokenSlot.Bytes())
for i := uint64(0); i < toTokenLength; i++ {
- toToken := common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, state.GetLocDynamicArrAtElement(toTokenSlotHash, i, uint64(1))).Bytes())
+ toToken := common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), state.GetLocDynamicArrAtElement(toTokenSlotHash, i, uint64(1))).Bytes())
log.Debug("GetAllTradingPairs all pair info", "from", fromTokens[i].Hex(), "toToken", toToken.Hex())
allPairs[GetTradingOrderBookHash(fromTokens[i], toToken)] = true
@@ -133,14 +137,14 @@ func SubRelayerFee(relayer common.Address, fee *big.Int, statedb *state.StateDB)
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance := statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance := statedb.GetState(relayerRegistrationSMC(statedb), locHashDeposit).Big()
log.Debug("ApplyXDCXMatchedTransaction settle balance: SubRelayerFee BEFORE", "relayer", relayer, "balance", balance)
if balance.Cmp(fee) < 0 {
return errors.Errorf("relayer %s isn't enough XDC fee", relayer)
} else {
balance = new(big.Int).Sub(balance, fee)
- statedb.SetState(common.RelayerRegistrationSMC, locHashDeposit, common.BigToHash(balance))
- statedb.SubBalance(common.RelayerRegistrationSMC, fee, tracing.BalanceChangeUnspecified)
+ statedb.SetState(relayerRegistrationSMC(statedb), locHashDeposit, common.BigToHash(balance))
+ statedb.SubBalance(relayerRegistrationSMC(statedb), fee, tracing.BalanceChangeUnspecified)
log.Debug("ApplyXDCXMatchedTransaction settle balance: SubRelayerFee AFTER", "relayer", relayer, "balance", balance)
return nil
}
@@ -152,7 +156,7 @@ func CheckRelayerFee(relayer common.Address, fee *big.Int, statedb *state.StateD
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance := statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance := statedb.GetState(relayerRegistrationSMC(statedb), locHashDeposit).Big()
if new(big.Int).Sub(balance, fee).Cmp(new(big.Int).Mul(common.BasePrice, common.RelayerLockedFund)) < 0 {
return errors.Errorf("relayer %s isn't enough XDC fee : balance %d , fee : %d ", relayer.Hex(), balance.Uint64(), fee.Uint64())
}
@@ -296,7 +300,7 @@ func CheckSubRelayerFee(relayer common.Address, fee *big.Int, statedb *state.Sta
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance = statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance = statedb.GetState(relayerRegistrationSMC(statedb), locHashDeposit).Big()
}
log.Debug("CheckSubRelayerFee settle balance: SubRelayerFee ", "relayer", relayer, "balance", balance, "fee", fee)
if balance.Cmp(fee) < 0 {
@@ -344,6 +348,6 @@ func SetSubRelayerFee(relayer common.Address, balance *big.Int, fee *big.Int, st
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- statedb.SetState(common.RelayerRegistrationSMC, locHashDeposit, common.BigToHash(balance))
- statedb.SubBalance(common.RelayerRegistrationSMC, fee, tracing.BalanceChangeUnspecified)
+ statedb.SetState(relayerRegistrationSMC(statedb), locHashDeposit, common.BigToHash(balance))
+ statedb.SubBalance(relayerRegistrationSMC(statedb), fee, tracing.BalanceChangeUnspecified)
}
diff --git a/XDCxlending/lendingstate/lendingcontract.go b/XDCxlending/lendingstate/lendingcontract.go
index 3e533d886b87..2381b690182a 100644
--- a/XDCxlending/lendingstate/lendingcontract.go
+++ b/XDCxlending/lendingstate/lendingcontract.go
@@ -36,6 +36,10 @@ var (
}
)
+func lendingRegistrationSMC(statedb *state.StateDB) common.Address {
+ return statedb.LendingRegistrationSMC()
+}
+
// @function IsValidRelayer : return whether the given address is the coinbase of a valid relayer or not
// @param statedb : current state
// @param coinbase: coinbase address of relayer
@@ -45,7 +49,7 @@ func IsValidRelayer(statedb *state.StateDB, coinbase common.Address) bool {
// a valid relayer must have baseToken
locBaseToken := state.GetLocOfStructElement(locRelayerState, LendingRelayerStructSlots["bases"])
- if v := statedb.GetState(common.LendingRegistrationSMC, common.BytesToHash(locBaseToken.Bytes())); v != (common.Hash{}) {
+ if v := statedb.GetState(lendingRegistrationSMC(statedb), common.BytesToHash(locBaseToken.Bytes())); v != (common.Hash{}) {
if tradingstate.IsResignedRelayer(coinbase, statedb) {
return false
}
@@ -54,7 +58,7 @@ func IsValidRelayer(statedb *state.StateDB, coinbase common.Address) bool {
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locRelayerStateTrading, tradingstate.RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance := statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance := statedb.GetState(statedb.RelayerRegistrationSMC(), locHashDeposit).Big()
expectedFund := new(big.Int).Mul(common.BasePrice, common.RelayerLockedFund)
if balance.Cmp(expectedFund) <= 0 {
log.Debug("Relayer is not in relayer list", "relayer", coinbase, "balance", balance, "expected", expectedFund)
@@ -72,7 +76,7 @@ func IsValidRelayer(statedb *state.StateDB, coinbase common.Address) bool {
func GetFee(statedb *state.StateDB, coinbase common.Address) *big.Int {
locRelayerState := state.GetLocMappingAtKey(coinbase.Hash(), LendingRelayerListSlot)
locHash := common.BytesToHash(new(big.Int).Add(locRelayerState, LendingRelayerStructSlots["fee"]).Bytes())
- return statedb.GetState(common.LendingRegistrationSMC, locHash).Big()
+ return statedb.GetState(lendingRegistrationSMC(statedb), locHash).Big()
}
// @function GetBaseList
@@ -83,10 +87,10 @@ func GetBaseList(statedb *state.StateDB, coinbase common.Address) []common.Addre
baseList := []common.Address{}
locRelayerState := state.GetLocMappingAtKey(coinbase.Hash(), LendingRelayerListSlot)
locBaseHash := state.GetLocOfStructElement(locRelayerState, LendingRelayerStructSlots["bases"])
- length := statedb.GetState(common.LendingRegistrationSMC, locBaseHash).Big().Uint64()
+ length := statedb.GetState(lendingRegistrationSMC(statedb), locBaseHash).Big().Uint64()
for i := uint64(0); i < length; i++ {
loc := state.GetLocDynamicArrAtElement(locBaseHash, i, 1)
- addr := common.BytesToAddress(statedb.GetState(common.LendingRegistrationSMC, loc).Bytes())
+ addr := common.BytesToAddress(statedb.GetState(lendingRegistrationSMC(statedb), loc).Bytes())
if addr != (common.Address{}) {
baseList = append(baseList, addr)
}
@@ -102,10 +106,10 @@ func GetTerms(statedb *state.StateDB, coinbase common.Address) []uint64 {
terms := []uint64{}
locRelayerState := state.GetLocMappingAtKey(coinbase.Hash(), LendingRelayerListSlot)
locTermHash := state.GetLocOfStructElement(locRelayerState, LendingRelayerStructSlots["terms"])
- length := statedb.GetState(common.LendingRegistrationSMC, locTermHash).Big().Uint64()
+ length := statedb.GetState(lendingRegistrationSMC(statedb), locTermHash).Big().Uint64()
for i := uint64(0); i < length; i++ {
loc := state.GetLocDynamicArrAtElement(locTermHash, i, 1)
- t := statedb.GetState(common.LendingRegistrationSMC, loc).Big().Uint64()
+ t := statedb.GetState(lendingRegistrationSMC(statedb), loc).Big().Uint64()
if t != uint64(0) {
terms = append(terms, t)
}
@@ -163,10 +167,10 @@ func GetCollaterals(statedb *state.StateDB, coinbase common.Address, baseToken c
// if collaterals is not defined for the relayer, return default collaterals
locDefaultCollateralHash := state.GetLocSimpleVariable(DefaultCollateralSlot)
- length := statedb.GetState(common.LendingRegistrationSMC, locDefaultCollateralHash).Big().Uint64()
+ length := statedb.GetState(lendingRegistrationSMC(statedb), locDefaultCollateralHash).Big().Uint64()
for i := uint64(0); i < length; i++ {
loc := state.GetLocDynamicArrAtElement(locDefaultCollateralHash, i, 1)
- addr := common.BytesToAddress(statedb.GetState(common.LendingRegistrationSMC, loc).Bytes())
+ addr := common.BytesToAddress(statedb.GetState(lendingRegistrationSMC(statedb), loc).Bytes())
if addr != (common.Address{}) {
collaterals = append(collaterals, addr)
}
@@ -183,9 +187,9 @@ func GetCollateralDetail(statedb *state.StateDB, token common.Address) (depositR
locDepositRate := state.GetLocOfStructElement(collateralState, CollateralStructSlots["depositRate"])
locLiquidationRate := state.GetLocOfStructElement(collateralState, CollateralStructSlots["liquidationRate"])
locRecallRate := state.GetLocOfStructElement(collateralState, CollateralStructSlots["recallRate"])
- depositRate = statedb.GetState(common.LendingRegistrationSMC, locDepositRate).Big()
- liquidationRate = statedb.GetState(common.LendingRegistrationSMC, locLiquidationRate).Big()
- recallRate = statedb.GetState(common.LendingRegistrationSMC, locRecallRate).Big()
+ depositRate = statedb.GetState(lendingRegistrationSMC(statedb), locDepositRate).Big()
+ liquidationRate = statedb.GetState(lendingRegistrationSMC(statedb), locLiquidationRate).Big()
+ recallRate = statedb.GetState(lendingRegistrationSMC(statedb), locRecallRate).Big()
return depositRate, liquidationRate, recallRate
}
@@ -197,8 +201,8 @@ func GetCollateralPrice(statedb *state.StateDB, collateralToken common.Address,
locCollateralPrice := common.BigToHash(new(big.Int).Add(new(big.Int).SetBytes(locLendingTokenPriceByte), PriceStructSlots["price"]))
locBlockNumber := common.BigToHash(new(big.Int).Add(new(big.Int).SetBytes(locLendingTokenPriceByte), PriceStructSlots["blockNumber"]))
- price = statedb.GetState(common.LendingRegistrationSMC, locCollateralPrice).Big()
- blockNumber = statedb.GetState(common.LendingRegistrationSMC, locBlockNumber).Big()
+ price = statedb.GetState(lendingRegistrationSMC(statedb), locCollateralPrice).Big()
+ blockNumber = statedb.GetState(lendingRegistrationSMC(statedb), locBlockNumber).Big()
return price, blockNumber
}
@@ -208,10 +212,10 @@ func GetCollateralPrice(statedb *state.StateDB, collateralToken common.Address,
func GetSupportedTerms(statedb *state.StateDB) []uint64 {
terms := []uint64{}
locSupportedTerm := state.GetLocSimpleVariable(SupportedTermSlot)
- length := statedb.GetState(common.LendingRegistrationSMC, locSupportedTerm).Big().Uint64()
+ length := statedb.GetState(lendingRegistrationSMC(statedb), locSupportedTerm).Big().Uint64()
for i := uint64(0); i < length; i++ {
loc := state.GetLocDynamicArrAtElement(locSupportedTerm, i, 1)
- t := statedb.GetState(common.LendingRegistrationSMC, loc).Big().Uint64()
+ t := statedb.GetState(lendingRegistrationSMC(statedb), loc).Big().Uint64()
if t != 0 {
terms = append(terms, t)
}
@@ -225,10 +229,10 @@ func GetSupportedTerms(statedb *state.StateDB) []uint64 {
func GetSupportedBaseToken(statedb *state.StateDB) []common.Address {
baseTokens := []common.Address{}
locSupportedBaseToken := state.GetLocSimpleVariable(SupportedBaseSlot)
- length := statedb.GetState(common.LendingRegistrationSMC, locSupportedBaseToken).Big().Uint64()
+ length := statedb.GetState(lendingRegistrationSMC(statedb), locSupportedBaseToken).Big().Uint64()
for i := uint64(0); i < length; i++ {
loc := state.GetLocDynamicArrAtElement(locSupportedBaseToken, i, 1)
- addr := common.BytesToAddress(statedb.GetState(common.LendingRegistrationSMC, loc).Bytes())
+ addr := common.BytesToAddress(statedb.GetState(lendingRegistrationSMC(statedb), loc).Bytes())
if addr != (common.Address{}) {
baseTokens = append(baseTokens, addr)
}
@@ -254,10 +258,10 @@ func GetAllCollateral(statedb *state.StateDB) []common.Address {
//}
locDefaultCollateralHash := state.GetLocSimpleVariable(DefaultCollateralSlot)
- length := statedb.GetState(common.LendingRegistrationSMC, locDefaultCollateralHash).Big().Uint64()
+ length := statedb.GetState(lendingRegistrationSMC(statedb), locDefaultCollateralHash).Big().Uint64()
for i := uint64(0); i < length; i++ {
loc := state.GetLocDynamicArrAtElement(locDefaultCollateralHash, i, 1)
- addr := common.BytesToAddress(statedb.GetState(common.LendingRegistrationSMC, loc).Bytes())
+ addr := common.BytesToAddress(statedb.GetState(lendingRegistrationSMC(statedb), loc).Bytes())
if addr != (common.Address{}) {
collaterals = append(collaterals, addr)
}
diff --git a/XDCxlending/lendingstate/lendingitem_test.go b/XDCxlending/lendingstate/lendingitem_test.go
index 9aefdb9a1dcf..0d75d72b4641 100644
--- a/XDCxlending/lendingstate/lendingitem_test.go
+++ b/XDCxlending/lendingstate/lendingitem_test.go
@@ -13,6 +13,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/crypto/keccak"
+ "github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/rpc"
)
@@ -159,7 +160,7 @@ func TestLendingItem_VerifyLendingStatus(t *testing.T) {
func SetFee(statedb *state.StateDB, coinbase common.Address, feeRate *big.Int) {
locRelayerState := state.GetLocMappingAtKey(coinbase.Hash(), LendingRelayerListSlot)
locHash := common.BytesToHash(new(big.Int).Add(locRelayerState, LendingRelayerStructSlots["fee"]).Bytes())
- statedb.SetState(common.LendingRegistrationSMC, locHash, common.BigToHash(feeRate))
+ statedb.SetState(statedb.LendingRegistrationSMC(), locHash, common.BigToHash(feeRate))
}
func SetCollateralDetail(statedb *state.StateDB, token common.Address, depositRate *big.Int, liquidationRate *big.Int, price *big.Int) {
@@ -167,14 +168,15 @@ func SetCollateralDetail(statedb *state.StateDB, token common.Address, depositRa
locDepositRate := state.GetLocOfStructElement(collateralState, CollateralStructSlots["depositRate"])
locLiquidationRate := state.GetLocOfStructElement(collateralState, CollateralStructSlots["liquidationRate"])
locCollateralPrice := state.GetLocOfStructElement(collateralState, CollateralStructSlots["price"])
- statedb.SetState(common.LendingRegistrationSMC, locDepositRate, common.BigToHash(depositRate))
- statedb.SetState(common.LendingRegistrationSMC, locLiquidationRate, common.BigToHash(liquidationRate))
- statedb.SetState(common.LendingRegistrationSMC, locCollateralPrice, common.BigToHash(price))
+ statedb.SetState(statedb.LendingRegistrationSMC(), locDepositRate, common.BigToHash(depositRate))
+ statedb.SetState(statedb.LendingRegistrationSMC(), locLiquidationRate, common.BigToHash(liquidationRate))
+ statedb.SetState(statedb.LendingRegistrationSMC(), locCollateralPrice, common.BigToHash(price))
}
func TestVerifyBalance(t *testing.T) {
db := rawdb.NewMemoryDatabase()
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(db))
+ statedb.SetChainConfig(params.LocalnetChainConfig)
relayer := common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")
uAddr := common.HexToAddress("0xDeE6238780f98c0ca2c2C28453149bEA49a3Abc9")
lendingToken := common.HexToAddress("0xd9bb01454c85247B2ef35BB5BE57384cC275a8cf") // USD
diff --git a/XDCxlending/lendingstate/relayer.go b/XDCxlending/lendingstate/relayer.go
index 829a759c17fe..fe1035313302 100644
--- a/XDCxlending/lendingstate/relayer.go
+++ b/XDCxlending/lendingstate/relayer.go
@@ -20,12 +20,16 @@ func GetLocMappingAtKey(key common.Hash, slot uint64) *big.Int {
return ret
}
+func relayerRegistrationSMC(statedb *state.StateDB) common.Address {
+ return statedb.RelayerRegistrationSMC()
+}
+
func GetExRelayerFee(relayer common.Address, statedb *state.StateDB) *big.Int {
slot := RelayerMappingSlot["RELAYER_LIST"]
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_fee"])
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash).Big()
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash).Big()
}
func GetRelayerOwner(relayer common.Address, statedb *state.StateDB) common.Address {
@@ -34,7 +38,7 @@ func GetRelayerOwner(relayer common.Address, statedb *state.StateDB) common.Addr
log.Debug("GetRelayerOwner", "relayer", relayer.Hex(), "slot", slot, "locBig", locBig)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_owner"])
locHash := common.BigToHash(locBig)
- return common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, locHash).Bytes())
+ return common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), locHash).Bytes())
}
// return true if relayer request to resign and have not withdraw locked fund
@@ -42,7 +46,7 @@ func IsResignedRelayer(relayer common.Address, statedb *state.StateDB) bool {
slot := RelayerMappingSlot["RESIGN_REQUESTS"]
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash) != (common.Hash{})
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash) != (common.Hash{})
}
func GetBaseTokenLength(relayer common.Address, statedb *state.StateDB) uint64 {
@@ -50,7 +54,7 @@ func GetBaseTokenLength(relayer common.Address, statedb *state.StateDB) uint64 {
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_fromTokens"])
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash).Big().Uint64()
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash).Big().Uint64()
}
func GetBaseTokenAtIndex(relayer common.Address, statedb *state.StateDB, index uint64) common.Address {
@@ -59,7 +63,7 @@ func GetBaseTokenAtIndex(relayer common.Address, statedb *state.StateDB, index u
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_fromTokens"])
locHash := common.BigToHash(locBig)
loc := state.GetLocDynamicArrAtElement(locHash, index, 1)
- return common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, loc).Bytes())
+ return common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), loc).Bytes())
}
func GetQuoteTokenLength(relayer common.Address, statedb *state.StateDB) uint64 {
@@ -67,7 +71,7 @@ func GetQuoteTokenLength(relayer common.Address, statedb *state.StateDB) uint64
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_toTokens"])
locHash := common.BigToHash(locBig)
- return statedb.GetState(common.RelayerRegistrationSMC, locHash).Big().Uint64()
+ return statedb.GetState(relayerRegistrationSMC(statedb), locHash).Big().Uint64()
}
func GetQuoteTokenAtIndex(relayer common.Address, statedb *state.StateDB, index uint64) common.Address {
@@ -76,7 +80,7 @@ func GetQuoteTokenAtIndex(relayer common.Address, statedb *state.StateDB, index
locBig = new(big.Int).Add(locBig, RelayerStructMappingSlot["_toTokens"])
locHash := common.BigToHash(locBig)
loc := state.GetLocDynamicArrAtElement(locHash, index, 1)
- return common.BytesToAddress(statedb.GetState(common.RelayerRegistrationSMC, loc).Bytes())
+ return common.BytesToAddress(statedb.GetState(relayerRegistrationSMC(statedb), loc).Bytes())
}
func SubRelayerFee(relayer common.Address, fee *big.Int, statedb *state.StateDB) error {
@@ -85,14 +89,14 @@ func SubRelayerFee(relayer common.Address, fee *big.Int, statedb *state.StateDB)
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance := statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance := statedb.GetState(relayerRegistrationSMC(statedb), locHashDeposit).Big()
log.Debug("ApplyXDCXMatchedTransaction settle balance: SubRelayerFee BEFORE", "relayer", relayer, "balance", balance)
if balance.Cmp(fee) < 0 {
return errors.Errorf("relayer %s isn't enough XDC fee", relayer)
} else {
balance = new(big.Int).Sub(balance, fee)
- statedb.SetState(common.RelayerRegistrationSMC, locHashDeposit, common.BigToHash(balance))
- statedb.SubBalance(common.RelayerRegistrationSMC, fee, tracing.BalanceChangeUnspecified)
+ statedb.SetState(relayerRegistrationSMC(statedb), locHashDeposit, common.BigToHash(balance))
+ statedb.SubBalance(relayerRegistrationSMC(statedb), fee, tracing.BalanceChangeUnspecified)
log.Debug("ApplyXDCXMatchedTransaction settle balance: SubRelayerFee AFTER", "relayer", relayer, "balance", balance)
return nil
}
@@ -104,7 +108,7 @@ func CheckRelayerFee(relayer common.Address, fee *big.Int, statedb *state.StateD
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance := statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance := statedb.GetState(relayerRegistrationSMC(statedb), locHashDeposit).Big()
if new(big.Int).Sub(balance, fee).Cmp(new(big.Int).Mul(common.BasePrice, common.RelayerLockedFund)) < 0 {
return errors.Errorf("relayer %s isn't enough XDC fee : balance %d , fee : %d ", relayer.Hex(), balance.Uint64(), fee.Uint64())
}
@@ -249,7 +253,7 @@ func CheckSubRelayerFee(relayer common.Address, fee *big.Int, statedb *state.Sta
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- balance = statedb.GetState(common.RelayerRegistrationSMC, locHashDeposit).Big()
+ balance = statedb.GetState(relayerRegistrationSMC(statedb), locHashDeposit).Big()
}
log.Debug("CheckSubRelayerFee settle balance: SubRelayerFee ", "relayer", relayer, "balance", balance, "fee", fee)
if balance.Cmp(fee) < 0 {
@@ -297,6 +301,6 @@ func SetSubRelayerFee(relayer common.Address, balance *big.Int, fee *big.Int, st
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
locBigDeposit := new(big.Int).SetUint64(uint64(0)).Add(locBig, RelayerStructMappingSlot["_deposit"])
locHashDeposit := common.BigToHash(locBigDeposit)
- statedb.SetState(common.RelayerRegistrationSMC, locHashDeposit, common.BigToHash(balance))
- statedb.SubBalance(common.RelayerRegistrationSMC, fee, tracing.BalanceChangeUnspecified)
+ statedb.SetState(relayerRegistrationSMC(statedb), locHashDeposit, common.BigToHash(balance))
+ statedb.SubBalance(relayerRegistrationSMC(statedb), fee, tracing.BalanceChangeUnspecified)
}
diff --git a/accounts/abi/abigen/bind_test.go b/accounts/abi/abigen/bind_test.go
index 19deeae42974..44d98a9bef93 100644
--- a/accounts/abi/abigen/bind_test.go
+++ b/accounts/abi/abigen/bind_test.go
@@ -298,7 +298,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy an interaction tester contract and call a transaction on it
@@ -355,7 +355,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a tuple tester contract and execute a structured call on it
@@ -402,7 +402,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a tuple tester contract and execute a structured call on it
@@ -461,7 +461,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a slice tester contract and execute a n array call on it
@@ -512,7 +512,7 @@ var bindTests = []struct {
config := *params.TestXDPoSMockChainConfig
config.Eip1559Block = big.NewInt(0)
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, &config)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, &config)
defer sim.Close()
// Deploy a default method invoker contract and execute its default method
@@ -580,7 +580,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a structs method invoker contract and execute its default method
@@ -713,7 +713,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a funky gas pattern contract
@@ -765,7 +765,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a sender tester contract and execute a structured call on it
@@ -841,7 +841,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a underscorer tester contract and execute a structured call on it
@@ -936,7 +936,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy an eventer contract
@@ -1128,7 +1128,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
//deploy the test contract
@@ -1266,7 +1266,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
_, _, contract, err := DeployTuple(auth, sim)
@@ -1406,7 +1406,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// deploy the test contract
@@ -1497,7 +1497,7 @@ var bindTests = []struct {
addr := crypto.PubkeyToAddress(key.PublicKey)
// Deploy registrar contract
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
transactOpts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
@@ -1560,7 +1560,7 @@ var bindTests = []struct {
addr := crypto.PubkeyToAddress(key.PublicKey)
// Deploy registrar contract
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
transactOpts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
@@ -1623,7 +1623,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
// Deploy a tester contract and execute a structured call on it
@@ -1684,7 +1684,7 @@ var bindTests = []struct {
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
- sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
+ sim := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(1000000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
defer sim.Close()
opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
diff --git a/accounts/abi/bind/v2/util_test.go b/accounts/abi/bind/v2/util_test.go
index 07d246c806da..03f30eba950b 100644
--- a/accounts/abi/bind/v2/util_test.go
+++ b/accounts/abi/bind/v2/util_test.go
@@ -56,7 +56,6 @@ var waitDeployedTests = map[string]struct {
func TestWaitDeployed(t *testing.T) {
t.Parallel()
config := *params.TestXDPoSMockChainConfig
- config.Eip1559Block = big.NewInt(0)
for name, test := range waitDeployedTests {
backend := simulated.New(
types.GenesisAlloc{
@@ -108,7 +107,6 @@ func TestWaitDeployed(t *testing.T) {
func TestWaitDeployedCornerCases(t *testing.T) {
config := *params.TestXDPoSMockChainConfig
- config.Eip1559Block = big.NewInt(0)
var (
backend = backends.NewXDCSimulatedBackend(
types.GenesisAlloc{
diff --git a/cmd/XDC/chaincmd.go b/cmd/XDC/chaincmd.go
index a4a45c40ba72..59536035d1cb 100644
--- a/cmd/XDC/chaincmd.go
+++ b/cmd/XDC/chaincmd.go
@@ -188,10 +188,6 @@ func initGenesis(ctx *cli.Context) error {
utils.Fatalf("invalid genesis json: %v", err)
}
- if genesis.Config.ChainID != nil {
- common.CopyConstants(genesis.Config.ChainID.Uint64())
- }
-
// Open and initialise both full and light databases
stack, _ := makeConfigNode(ctx)
defer stack.Close()
@@ -201,10 +197,13 @@ func initGenesis(ctx *cli.Context) error {
if err != nil {
utils.Fatalf("Failed to open database: %v", err)
}
- _, hash, err := core.SetupGenesisBlock(chaindb, genesis)
+ _, hash, compatErr, err := core.SetupGenesisBlock(chaindb, genesis)
if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err)
}
+ if compatErr != nil {
+ utils.Fatalf("Failed to write chain config: %v", compatErr)
+ }
chaindb.Close()
log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
return nil
diff --git a/cmd/XDC/dao_test.go b/cmd/XDC/dao_test.go
index e46398b6404c..37e6b5ee9da6 100644
--- a/cmd/XDC/dao_test.go
+++ b/cmd/XDC/dao_test.go
@@ -31,13 +31,19 @@ var daoOldGenesis = `{
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
- "extraData" : "",
+ "extraData" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
- "config" : {}
+ "config" : {
+ "chainId" : 1337,
+ "tipTRC21FeeBlock" : 0,
+ "XDPoS": {
+ "maxMasternodesV2": 108
+ }
+ }
}`
// Genesis block for nodes which actively oppose the DAO fork
@@ -45,15 +51,20 @@ var daoNoForkGenesis = `{
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
- "extraData" : "",
+ "extraData" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
"config" : {
+ "chainId" : 1337,
+ "tipTRC21FeeBlock" : 0,
"daoForkBlock" : 314,
- "daoForkSupport" : false
+ "daoForkSupport" : false,
+ "XDPoS": {
+ "maxMasternodesV2": 108
+ }
}
}`
@@ -62,19 +73,23 @@ var daoProForkGenesis = `{
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
- "extraData" : "",
+ "extraData" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
"config" : {
+ "chainId" : 1337,
+ "tipTRC21FeeBlock" : 0,
"daoForkBlock" : 314,
- "daoForkSupport" : true
+ "daoForkSupport" : true,
+ "XDPoS": {
+ "maxMasternodesV2": 108
+ }
}
}`
-var daoGenesisHash = common.HexToHash("29a4b5d743bfbda3a7461974d49c62bf23ba5df9c8b01de8256e2ac2a9ae1cd8")
var daoGenesisForkBlock = big.NewInt(314)
// TestDAOForkBlockNewChain tests that the DAO hard-fork number and the nodes support/opposition is correctly
@@ -122,9 +137,10 @@ func testDAOForkBlockNewChain(t *testing.T, test int, genesis string, expectBloc
}
defer db.Close()
- genesisHash := common.HexToHash("8d13370621558f4ed0da587934473c0404729f28b0ff1d50e5fdd840457a2f17")
- if genesis != "" {
- genesisHash = daoGenesisHash
+ genesisHash := rawdb.ReadCanonicalHash(db, 0)
+ if genesisHash == (common.Hash{}) {
+ t.Errorf("test %d: failed to read canonical genesis hash", test)
+ return
}
config, err := rawdb.ReadChainConfig(db, genesisHash)
if err != nil {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 1928060037af..8eeef3b0d2fc 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -1595,18 +1595,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
switch {
case ctx.Bool(MainnetFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
- cfg.NetworkId = 50
+ cfg.NetworkId = params.XDCMainnetChainConfig.ChainID.Uint64() // 50
}
cfg.Genesis = core.DefaultGenesisBlock()
case ctx.Bool(TestnetFlag.Name):
common.IsTestnet = true
if !ctx.IsSet(NetworkIdFlag.Name) {
- cfg.NetworkId = 51
+ cfg.NetworkId = params.TestnetChainConfig.ChainID.Uint64() // 51
}
cfg.Genesis = core.DefaultTestnetGenesisBlock()
case ctx.Bool(DevnetFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
- cfg.NetworkId = 5551
+ cfg.NetworkId = params.DevnetChainConfig.ChainID.Uint64() // 5551
}
cfg.Genesis = core.DefaultDevnetGenesisBlock()
case ctx.Bool(DeveloperFlag.Name):
@@ -1676,12 +1676,12 @@ func SetNetworkFlagById(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name)
switch cfg.NetworkId {
- case 50:
+ case params.XDCMainnetChainConfig.ChainID.Uint64(): // 50
ctx.Set(MainnetFlag.Name, "true")
- case 51:
+ case params.TestnetChainConfig.ChainID.Uint64(): // 51
common.IsTestnet = true
ctx.Set(TestnetFlag.Name, "true")
- case 5551:
+ case params.DevnetChainConfig.ChainID.Uint64(): // 5551
ctx.Set(DevnetFlag.Name, "true")
}
}
diff --git a/common/bigint.go b/common/bigint.go
new file mode 100644
index 000000000000..6ebab82ec750
--- /dev/null
+++ b/common/bigint.go
@@ -0,0 +1,11 @@
+package common
+
+import "math/big"
+
+// CloneBigInt returns a deep copy of value. It returns nil if value is nil.
+func CloneBigInt(value *big.Int) *big.Int {
+ if value == nil {
+ return nil
+ }
+ return new(big.Int).Set(value)
+}
diff --git a/common/constants.all.go b/common/constants.all.go
index f84028eefbd7..f421d735b2c1 100644
--- a/common/constants.all.go
+++ b/common/constants.all.go
@@ -1,11 +1,7 @@
package common
import (
- "fmt"
- "maps"
"math/big"
-
- "github.com/XinFinOrg/XDPoSChain/log"
)
// non-const variables for all network.
@@ -39,194 +35,3 @@ var (
RelayerLendingFee = big.NewInt(10000000000000000) // 0.01
RelayerLendingCancelFee = big.NewInt(1000000000000000) // 0.001
)
-
-type constant struct {
- chainID uint64
- denylistHFNumber uint64
- maxMasternodesV2 int // Last v1 masternodes
-
- tip2019Block *big.Int
- tipSigning *big.Int
- tipRandomize *big.Int
- tipNoHalvingMNReward *big.Int // hard fork no halving masternodes reward
- tipXDCX *big.Int
- tipXDCXLending *big.Int
- tipXDCXCancellationFee *big.Int
- tipTRC21Fee *big.Int
- tipIncreaseMasternodes *big.Int // Upgrade MN Count at Block.
- berlinBlock *big.Int
- londonBlock *big.Int
- mergeBlock *big.Int
- shanghaiBlock *big.Int
- blockNumberGas50x *big.Int
- TIPV2SwitchBlock *big.Int
- tipXDCXMinerDisable *big.Int
- tipXDCXReceiverDisable *big.Int
- tipUpgradeReward *big.Int
- tipUpgradePenalty *big.Int
- tipEpochHalving *big.Int
- eip1559Block *big.Int
- cancunBlock *big.Int
- pragueBlock *big.Int
- osakaBlock *big.Int
- dynamicGasLimitBlock *big.Int
-
- trc21IssuerSMC Address
- xdcxListingSMC Address
- relayerRegistrationSMC Address
- lendingRegistrationSMC Address
-
- ignoreSignerCheckBlockArray map[uint64]struct{}
-
- denylist map[Address]struct{}
-}
-
-func (c *constant) print() {
- fmt.Println("chainID:", c.chainID)
- fmt.Println("denylistHFNumber:", c.denylistHFNumber)
- fmt.Println("maxMasternodesV2:", c.maxMasternodesV2)
- fmt.Println("tip2019Block:", c.tip2019Block)
- fmt.Println("tipSigning:", c.tipSigning)
- fmt.Println("tipRandomize:", c.tipRandomize)
- fmt.Println("tipNoHalvingMNReward:", c.tipNoHalvingMNReward)
- fmt.Println("tipXDCX:", c.tipXDCX)
- fmt.Println("tipXDCXLending:", c.tipXDCXLending)
- fmt.Println("tipXDCXCancellationFee:", c.tipXDCXCancellationFee)
- fmt.Println("tipTRC21Fee:", c.tipTRC21Fee)
- fmt.Println("tipIncreaseMasternodes:", c.tipIncreaseMasternodes)
- fmt.Println("berlinBlock:", c.berlinBlock)
- fmt.Println("londonBlock:", c.londonBlock)
- fmt.Println("mergeBlock:", c.mergeBlock)
- fmt.Println("shanghaiBlock:", c.shanghaiBlock)
- fmt.Println("blockNumberGas50x:", c.blockNumberGas50x)
- fmt.Println("TIPV2SwitchBlock:", c.TIPV2SwitchBlock)
- fmt.Println("tipXDCXMinerDisable:", c.tipXDCXMinerDisable)
- fmt.Println("tipXDCXReceiverDisable:", c.tipXDCXReceiverDisable)
- fmt.Println("tipUpgradeReward:", c.tipUpgradeReward)
- fmt.Println("tipUpgradePenalty:", c.tipUpgradePenalty)
- fmt.Println("tipEpochHalving:", c.tipEpochHalving)
- fmt.Println("eip1559Block:", c.eip1559Block)
- fmt.Println("cancunBlock:", c.cancunBlock)
- fmt.Println("pragueBlock:", c.pragueBlock)
- fmt.Println("osakaBlock:", c.osakaBlock)
- fmt.Println("dynamicGasLimitBlock:", c.dynamicGasLimitBlock)
- fmt.Println("trc21IssuerSMC:", c.trc21IssuerSMC)
- fmt.Println("xdcxListingSMC:", c.xdcxListingSMC)
- fmt.Println("relayerRegistrationSMC:", c.relayerRegistrationSMC)
- fmt.Println("lendingRegistrationSMC:", c.lendingRegistrationSMC)
- fmt.Println("ignoreSignerCheckBlockArray:", c.ignoreSignerCheckBlockArray)
- fmt.Println("denylist:", c.denylist)
-}
-
-// variables for specific networks, copy values from mainnet constant to pass tests
-var (
- DenylistHFNumber = MainnetConstant.denylistHFNumber
- MaxMasternodesV2 = MainnetConstant.maxMasternodesV2 // Last v1 masternodes
-
- TIP2019Block = MainnetConstant.tip2019Block
- TIPSigning = MainnetConstant.tipSigning
- TIPRandomize = MainnetConstant.tipRandomize
- TIPNoHalvingMNReward = MainnetConstant.tipNoHalvingMNReward
- TIPXDCX = MainnetConstant.tipXDCX
- TIPXDCXLending = MainnetConstant.tipXDCXLending
- TIPXDCXCancellationFee = MainnetConstant.tipXDCXCancellationFee
- TIPTRC21Fee = MainnetConstant.tipTRC21Fee
- TIPIncreaseMasternodes = MainnetConstant.tipIncreaseMasternodes
- BerlinBlock = MainnetConstant.berlinBlock
- LondonBlock = MainnetConstant.londonBlock
- MergeBlock = MainnetConstant.mergeBlock
- ShanghaiBlock = MainnetConstant.shanghaiBlock
- BlockNumberGas50x = MainnetConstant.blockNumberGas50x
- TIPXDCXMinerDisable = MainnetConstant.tipXDCXMinerDisable
- TIPXDCXReceiverDisable = MainnetConstant.tipXDCXReceiverDisable
- Eip1559Block = MainnetConstant.eip1559Block
- CancunBlock = MainnetConstant.cancunBlock
- PragueBlock = MainnetConstant.pragueBlock
- OsakaBlock = MainnetConstant.osakaBlock
- DynamicGasLimitBlock = MainnetConstant.dynamicGasLimitBlock
- TIPUpgradeReward = MainnetConstant.tipUpgradeReward
- TipUpgradePenalty = MainnetConstant.tipUpgradePenalty
- TIPEpochHalving = MainnetConstant.tipEpochHalving
-
- TRC21IssuerSMC = MainnetConstant.trc21IssuerSMC
- XDCXListingSMC = MainnetConstant.xdcxListingSMC
- RelayerRegistrationSMC = MainnetConstant.relayerRegistrationSMC
- LendingRegistrationSMC = MainnetConstant.lendingRegistrationSMC
-
- ignoreSignerCheckBlockArray = MainnetConstant.ignoreSignerCheckBlockArray
- denylist = MainnetConstant.denylist
-)
-
-func IsIgnoreSignerCheckBlock(blockNumber uint64) bool {
- _, ok := ignoreSignerCheckBlockArray[blockNumber]
- return ok
-}
-
-func IsInDenylist(address *Address) bool {
- if address == nil {
- return false
- }
- _, ok := denylist[*address]
- return ok
-}
-
-// CopyConstants only handles testnet, devnet, local network.
-// It skips mainnet since the default value is from mainnet.
-func CopyConstants(chainID uint64) {
- log.Info("[CopyConstants]", "chainID", chainID)
- var c *constant
- switch chainID {
- case MainnetConstant.chainID:
- log.Info("[CopyConstants] mainnet chainID matched, no need to copy constants")
- return
- case TestnetConstant.chainID:
- log.Info("[CopyConstants] testnet chainID matched, copying testnet constants")
- c = &TestnetConstant
- IsTestnet = true
- case DevnetConstant.chainID:
- log.Info("[CopyConstants] devnet chainID matched, copying devnet constants")
- c = &DevnetConstant
- default: // local custom chain, it can have any chainID
- log.Info("[CopyConstants] local chainID matched, copying local constants")
- c = &localConstant
- }
- c.print()
-
- MaxMasternodesV2 = c.maxMasternodesV2
- DenylistHFNumber = c.denylistHFNumber
- TIP2019Block = c.tip2019Block
- TIPSigning = c.tipSigning
- TIPRandomize = c.tipRandomize
- TIPNoHalvingMNReward = c.tipNoHalvingMNReward
- TIPXDCX = c.tipXDCX
- TIPXDCXLending = c.tipXDCXLending
- TIPXDCXCancellationFee = c.tipXDCXCancellationFee
- TIPTRC21Fee = c.tipTRC21Fee
- TIPIncreaseMasternodes = c.tipIncreaseMasternodes
- BerlinBlock = c.berlinBlock
- LondonBlock = c.londonBlock
- MergeBlock = c.mergeBlock
- ShanghaiBlock = c.shanghaiBlock
- BlockNumberGas50x = c.blockNumberGas50x
- TIPXDCXMinerDisable = c.tipXDCXMinerDisable
- TIPXDCXReceiverDisable = c.tipXDCXReceiverDisable
- Eip1559Block = c.eip1559Block
- CancunBlock = c.cancunBlock
- PragueBlock = c.pragueBlock
- OsakaBlock = c.osakaBlock
- DynamicGasLimitBlock = c.dynamicGasLimitBlock
- TIPUpgradeReward = c.tipUpgradeReward
- TipUpgradePenalty = c.tipUpgradePenalty
- TIPEpochHalving = c.tipEpochHalving
-
- TRC21IssuerSMC = c.trc21IssuerSMC
- XDCXListingSMC = c.xdcxListingSMC
- RelayerRegistrationSMC = c.relayerRegistrationSMC
- LendingRegistrationSMC = c.lendingRegistrationSMC
-
- clear(ignoreSignerCheckBlockArray)
- maps.Copy(ignoreSignerCheckBlockArray, c.ignoreSignerCheckBlockArray)
-
- clear(denylist)
- maps.Copy(denylist, c.denylist)
-}
diff --git a/common/constants.devnet.go b/common/constants.devnet.go
deleted file mode 100644
index b409d62bf90f..000000000000
--- a/common/constants.devnet.go
+++ /dev/null
@@ -1,114 +0,0 @@
-package common
-
-import (
- "math"
- "math/big"
-)
-
-var DevnetConstant = constant{
- chainID: 5551,
- denylistHFNumber: 0,
- maxMasternodesV2: 108,
-
- tip2019Block: big.NewInt(0),
- tipSigning: big.NewInt(0),
- tipRandomize: big.NewInt(0),
- tipNoHalvingMNReward: big.NewInt(0),
- tipXDCX: big.NewInt(0),
- tipXDCXLending: big.NewInt(0),
- tipXDCXCancellationFee: big.NewInt(0),
- tipTRC21Fee: big.NewInt(0),
- tipIncreaseMasternodes: big.NewInt(0),
- berlinBlock: big.NewInt(0),
- londonBlock: big.NewInt(0),
- mergeBlock: big.NewInt(0),
- shanghaiBlock: big.NewInt(0),
- blockNumberGas50x: big.NewInt(0),
- TIPV2SwitchBlock: big.NewInt(2700),
- tipXDCXMinerDisable: big.NewInt(0),
- tipXDCXReceiverDisable: big.NewInt(0),
- eip1559Block: big.NewInt(250000),
- cancunBlock: big.NewInt(250000),
- pragueBlock: big.NewInt(5000000),
- osakaBlock: big.NewInt(math.MaxInt64),
- dynamicGasLimitBlock: big.NewInt(5000000),
- tipUpgradeReward: big.NewInt(5000000),
- tipUpgradePenalty: big.NewInt(5000000),
- tipEpochHalving: big.NewInt(math.MaxInt64),
-
- trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
- xdcxListingSMC: HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
- relayerRegistrationSMC: HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
- lendingRegistrationSMC: HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
-
- ignoreSignerCheckBlockArray: map[uint64]struct{}{
- 1032300: {},
- 1033200: {},
- 27307800: {},
- 28270800: {},
- },
-
- denylist: map[Address]struct{}{
- HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd"): {},
- HexToAddress("0x5ac26105b35ea8935be382863a70281ec7a985e9"): {},
- HexToAddress("0x09c4f991a41e7ca0645d7dfbfee160b55e562ea4"): {},
- HexToAddress("0xb3157bbc5b401a45d6f60b106728bb82ebaa585b"): {},
- HexToAddress("0x741277a8952128d5c2ffe0550f5001e4c8247674"): {},
- HexToAddress("0x10ba49c1caa97d74b22b3e74493032b180cebe01"): {},
- HexToAddress("0x07048d51d9e6179578a6e3b9ee28cdc183b865e4"): {},
- HexToAddress("0x4b899001d73c7b4ec404a771d37d9be13b8983de"): {},
- HexToAddress("0x85cb320a9007f26b7652c19a2a65db1da2d0016f"): {},
- HexToAddress("0x06869dbd0e3a2ea37ddef832e20fa005c6f0ca39"): {},
- HexToAddress("0x82e48bc7e2c93d89125428578fb405947764ad7c"): {},
- HexToAddress("0x1f9a78534d61732367cbb43fc6c89266af67c989"): {},
- HexToAddress("0x7c3b1fa91df55ff7af0cad9e0399384dc5c6641b"): {},
- HexToAddress("0x5888dc1ceb0ff632713486b9418e59743af0fd20"): {},
- HexToAddress("0xa512fa1c735fc3cc635624d591dd9ea1ce339ca5"): {},
- HexToAddress("0x0832517654c7b7e36b1ef45d76de70326b09e2c7"): {},
- HexToAddress("0xca14e3c4c78bafb60819a78ff6e6f0f709d2aea7"): {},
- HexToAddress("0x652ce195a23035114849f7642b0e06647d13e57a"): {},
- HexToAddress("0x29a79f00f16900999d61b6e171e44596af4fb5ae"): {},
- HexToAddress("0xf9fd1c2b0af0d91b0b6754e55639e3f8478dd04a"): {},
- HexToAddress("0xb835710c9901d5fe940ef1b99ed918902e293e35"): {},
- HexToAddress("0x04dd29ce5c253377a9a3796103ea0d9a9e514153"): {},
- HexToAddress("0x2b4b56846eaf05c1fd762b5e1ac802efd0ab871c"): {},
- HexToAddress("0x1d1f909f6600b23ce05004f5500ab98564717996"): {},
- HexToAddress("0x0dfdcebf80006dc9ab7aae8c216b51c6b6759e86"): {},
- HexToAddress("0x2b373890a28e5e46197fbc04f303bbfdd344056f"): {},
- HexToAddress("0xa8a3ef3dc5d8e36aee76f3671ec501ec31e28254"): {},
- HexToAddress("0x4f3d18136fe2b5665c29bdaf74591fc6625ef427"): {},
- HexToAddress("0x175d728b0e0f1facb5822a2e0c03bde93596e324"): {},
- HexToAddress("0xd575c2611984fcd79513b80ab94f59dc5bab4916"): {},
- HexToAddress("0x0579337873c97c4ba051310236ea847f5be41bc0"): {},
- HexToAddress("0xed12a519cc15b286920fc15fd86106b3e6a16218"): {},
- HexToAddress("0x492d26d852a0a0a2982bb40ec86fe394488c419e"): {},
- HexToAddress("0xce5c7635d02dc4e1d6b46c256cae6323be294a32"): {},
- HexToAddress("0x8b94db158b5e78a6c032c7e7c9423dec62c8b11c"): {},
- HexToAddress("0x0e7c48c085b6b0aa7ca6e4cbcc8b9a92dc270eb4"): {},
- HexToAddress("0x206e6508462033ef8425edc6c10789d241d49acb"): {},
- HexToAddress("0x7710e7b7682f26cb5a1202e1cff094fbf7777758"): {},
- HexToAddress("0xcb06f949313b46bbf53b8e6b2868a0c260ff9385"): {},
- HexToAddress("0xf884e43533f61dc2997c0e19a6eff33481920c00"): {},
- HexToAddress("0x8b635ef2e4c8fe21fc2bda027eb5f371d6aa2fc1"): {},
- HexToAddress("0x10f01a27cf9b29d02ce53497312b96037357a361"): {},
- HexToAddress("0x693dd49b0ed70f162d733cf20b6c43dc2a2b4d95"): {},
- HexToAddress("0xe0bec72d1c2a7a7fb0532cdfac44ebab9f6f41ee"): {},
- HexToAddress("0xc8793633a537938cb49cdbbffd45428f10e45b64"): {},
- HexToAddress("0x0d07a6cbbe9fa5c4f154e5623bfe47fb4d857d8e"): {},
- HexToAddress("0xd4080b289da95f70a586610c38268d8d4cf1e4c4"): {},
- HexToAddress("0x8bcfb0caf41f0aa1b548cae76dcdd02e33866a1b"): {},
- HexToAddress("0xabfef22b92366d3074676e77ea911ccaabfb64c1"): {},
- HexToAddress("0xcc4df7a32faf3efba32c9688def5ccf9fefe443d"): {},
- HexToAddress("0x7ec1e48a582475f5f2b7448a86c4ea7a26ea36f8"): {},
- HexToAddress("0xe3de67289080f63b0c2612844256a25bb99ac0ad"): {},
- HexToAddress("0x3ba623300cf9e48729039b3c9e0dee9b785d636e"): {},
- HexToAddress("0x402f2cfc9c8942f5e7a12c70c625d07a5d52fe29"): {},
- HexToAddress("0xd62358d42afbde095a4ca868581d85f9adcc3d61"): {},
- HexToAddress("0x3969f86acb733526cd61e3c6e3b4660589f32bc6"): {},
- HexToAddress("0x67615413d7cdadb2c435a946aec713a9a9794d39"): {},
- HexToAddress("0xfe685f43acc62f92ab01a8da80d76455d39d3cb3"): {},
- HexToAddress("0x3538a544021c07869c16b764424c5987409cba48"): {},
- HexToAddress("0xe187cf86c2274b1f16e8225a7da9a75aba4f1f5f"): {},
- HexToAddress("0x0000000000000000000000000000000000000011"): {},
- },
-}
diff --git a/common/constants.local.go b/common/constants.local.go
deleted file mode 100644
index a21b4501e2fd..000000000000
--- a/common/constants.local.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package common
-
-import (
- "math"
- "math/big"
-)
-
-var localConstant = constant{
- chainID: 5151,
- maxMasternodesV2: 108,
- denylistHFNumber: 0,
-
- tip2019Block: big.NewInt(0),
- tipSigning: big.NewInt(0),
- tipRandomize: big.NewInt(0),
- tipNoHalvingMNReward: big.NewInt(0),
- tipXDCX: big.NewInt(0),
- tipXDCXLending: big.NewInt(0),
- tipXDCXCancellationFee: big.NewInt(0),
- tipTRC21Fee: big.NewInt(0),
- tipIncreaseMasternodes: big.NewInt(0),
- berlinBlock: big.NewInt(0),
- londonBlock: big.NewInt(0),
- mergeBlock: big.NewInt(0),
- shanghaiBlock: big.NewInt(0),
- blockNumberGas50x: big.NewInt(0),
- TIPV2SwitchBlock: big.NewInt(0),
- tipXDCXMinerDisable: big.NewInt(0),
- tipXDCXReceiverDisable: big.NewInt(0),
- eip1559Block: big.NewInt(0),
- cancunBlock: big.NewInt(0),
- pragueBlock: big.NewInt(math.MaxInt64),
- osakaBlock: big.NewInt(math.MaxInt64),
- dynamicGasLimitBlock: big.NewInt(math.MaxInt64),
- tipUpgradeReward: big.NewInt(math.MaxInt64),
- tipUpgradePenalty: big.NewInt(math.MaxInt64),
- tipEpochHalving: big.NewInt(math.MaxInt64),
-
- trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
- xdcxListingSMC: HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
- relayerRegistrationSMC: HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
- lendingRegistrationSMC: HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
-
- ignoreSignerCheckBlockArray: map[uint64]struct{}{},
-
- denylist: map[Address]struct{}{},
-}
diff --git a/common/constants.mainnet.go b/common/constants.mainnet.go
deleted file mode 100644
index 006b47497ead..000000000000
--- a/common/constants.mainnet.go
+++ /dev/null
@@ -1,114 +0,0 @@
-package common
-
-import (
- "math"
- "math/big"
-)
-
-var MainnetConstant = constant{
- chainID: 50,
- denylistHFNumber: 38383838,
- maxMasternodesV2: 108,
-
- tip2019Block: big.NewInt(1),
- tipSigning: big.NewInt(3000000),
- tipRandomize: big.NewInt(3464000),
- tipNoHalvingMNReward: big.NewInt(38383838),
- tipXDCX: big.NewInt(38383838),
- tipXDCXLending: big.NewInt(38383838),
- tipXDCXCancellationFee: big.NewInt(38383838),
- tipTRC21Fee: big.NewInt(38383838),
- tipIncreaseMasternodes: big.NewInt(5000000),
- berlinBlock: big.NewInt(76321000), // Target 19th June 2024
- londonBlock: big.NewInt(76321000), // Target 19th June 2024
- mergeBlock: big.NewInt(76321000), // Target 19th June 2024
- shanghaiBlock: big.NewInt(76321000), // Target 19th June 2024
- blockNumberGas50x: big.NewInt(80370000), // Target 2nd Oct 2024
- TIPV2SwitchBlock: big.NewInt(80370000), // Target 2nd Oct 2024
- tipXDCXMinerDisable: big.NewInt(80370000), // Target 2nd Oct 2024
- tipXDCXReceiverDisable: big.NewInt(80370900), // Target 2nd Oct 2024, safer to release after disable miner
- eip1559Block: big.NewInt(98800200), // Target 28th Jan 2026
- cancunBlock: big.NewInt(98802000), // Target 28th Jan 2026
- pragueBlock: big.NewInt(math.MaxInt64),
- osakaBlock: big.NewInt(math.MaxInt64),
- dynamicGasLimitBlock: big.NewInt(math.MaxInt64),
- tipUpgradeReward: big.NewInt(math.MaxInt64),
- tipUpgradePenalty: big.NewInt(math.MaxInt64),
- tipEpochHalving: big.NewInt(math.MaxInt64),
-
- trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
- xdcxListingSMC: HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
- relayerRegistrationSMC: HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
- lendingRegistrationSMC: HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
-
- ignoreSignerCheckBlockArray: map[uint64]struct{}{
- 1032300: {},
- 1033200: {},
- 27307800: {},
- 28270800: {},
- },
-
- denylist: map[Address]struct{}{
- HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd"): {},
- HexToAddress("0x5ac26105b35ea8935be382863a70281ec7a985e9"): {},
- HexToAddress("0x09c4f991a41e7ca0645d7dfbfee160b55e562ea4"): {},
- HexToAddress("0xb3157bbc5b401a45d6f60b106728bb82ebaa585b"): {},
- HexToAddress("0x741277a8952128d5c2ffe0550f5001e4c8247674"): {},
- HexToAddress("0x10ba49c1caa97d74b22b3e74493032b180cebe01"): {},
- HexToAddress("0x07048d51d9e6179578a6e3b9ee28cdc183b865e4"): {},
- HexToAddress("0x4b899001d73c7b4ec404a771d37d9be13b8983de"): {},
- HexToAddress("0x85cb320a9007f26b7652c19a2a65db1da2d0016f"): {},
- HexToAddress("0x06869dbd0e3a2ea37ddef832e20fa005c6f0ca39"): {},
- HexToAddress("0x82e48bc7e2c93d89125428578fb405947764ad7c"): {},
- HexToAddress("0x1f9a78534d61732367cbb43fc6c89266af67c989"): {},
- HexToAddress("0x7c3b1fa91df55ff7af0cad9e0399384dc5c6641b"): {},
- HexToAddress("0x5888dc1ceb0ff632713486b9418e59743af0fd20"): {},
- HexToAddress("0xa512fa1c735fc3cc635624d591dd9ea1ce339ca5"): {},
- HexToAddress("0x0832517654c7b7e36b1ef45d76de70326b09e2c7"): {},
- HexToAddress("0xca14e3c4c78bafb60819a78ff6e6f0f709d2aea7"): {},
- HexToAddress("0x652ce195a23035114849f7642b0e06647d13e57a"): {},
- HexToAddress("0x29a79f00f16900999d61b6e171e44596af4fb5ae"): {},
- HexToAddress("0xf9fd1c2b0af0d91b0b6754e55639e3f8478dd04a"): {},
- HexToAddress("0xb835710c9901d5fe940ef1b99ed918902e293e35"): {},
- HexToAddress("0x04dd29ce5c253377a9a3796103ea0d9a9e514153"): {},
- HexToAddress("0x2b4b56846eaf05c1fd762b5e1ac802efd0ab871c"): {},
- HexToAddress("0x1d1f909f6600b23ce05004f5500ab98564717996"): {},
- HexToAddress("0x0dfdcebf80006dc9ab7aae8c216b51c6b6759e86"): {},
- HexToAddress("0x2b373890a28e5e46197fbc04f303bbfdd344056f"): {},
- HexToAddress("0xa8a3ef3dc5d8e36aee76f3671ec501ec31e28254"): {},
- HexToAddress("0x4f3d18136fe2b5665c29bdaf74591fc6625ef427"): {},
- HexToAddress("0x175d728b0e0f1facb5822a2e0c03bde93596e324"): {},
- HexToAddress("0xd575c2611984fcd79513b80ab94f59dc5bab4916"): {},
- HexToAddress("0x0579337873c97c4ba051310236ea847f5be41bc0"): {},
- HexToAddress("0xed12a519cc15b286920fc15fd86106b3e6a16218"): {},
- HexToAddress("0x492d26d852a0a0a2982bb40ec86fe394488c419e"): {},
- HexToAddress("0xce5c7635d02dc4e1d6b46c256cae6323be294a32"): {},
- HexToAddress("0x8b94db158b5e78a6c032c7e7c9423dec62c8b11c"): {},
- HexToAddress("0x0e7c48c085b6b0aa7ca6e4cbcc8b9a92dc270eb4"): {},
- HexToAddress("0x206e6508462033ef8425edc6c10789d241d49acb"): {},
- HexToAddress("0x7710e7b7682f26cb5a1202e1cff094fbf7777758"): {},
- HexToAddress("0xcb06f949313b46bbf53b8e6b2868a0c260ff9385"): {},
- HexToAddress("0xf884e43533f61dc2997c0e19a6eff33481920c00"): {},
- HexToAddress("0x8b635ef2e4c8fe21fc2bda027eb5f371d6aa2fc1"): {},
- HexToAddress("0x10f01a27cf9b29d02ce53497312b96037357a361"): {},
- HexToAddress("0x693dd49b0ed70f162d733cf20b6c43dc2a2b4d95"): {},
- HexToAddress("0xe0bec72d1c2a7a7fb0532cdfac44ebab9f6f41ee"): {},
- HexToAddress("0xc8793633a537938cb49cdbbffd45428f10e45b64"): {},
- HexToAddress("0x0d07a6cbbe9fa5c4f154e5623bfe47fb4d857d8e"): {},
- HexToAddress("0xd4080b289da95f70a586610c38268d8d4cf1e4c4"): {},
- HexToAddress("0x8bcfb0caf41f0aa1b548cae76dcdd02e33866a1b"): {},
- HexToAddress("0xabfef22b92366d3074676e77ea911ccaabfb64c1"): {},
- HexToAddress("0xcc4df7a32faf3efba32c9688def5ccf9fefe443d"): {},
- HexToAddress("0x7ec1e48a582475f5f2b7448a86c4ea7a26ea36f8"): {},
- HexToAddress("0xe3de67289080f63b0c2612844256a25bb99ac0ad"): {},
- HexToAddress("0x3ba623300cf9e48729039b3c9e0dee9b785d636e"): {},
- HexToAddress("0x402f2cfc9c8942f5e7a12c70c625d07a5d52fe29"): {},
- HexToAddress("0xd62358d42afbde095a4ca868581d85f9adcc3d61"): {},
- HexToAddress("0x3969f86acb733526cd61e3c6e3b4660589f32bc6"): {},
- HexToAddress("0x67615413d7cdadb2c435a946aec713a9a9794d39"): {},
- HexToAddress("0xfe685f43acc62f92ab01a8da80d76455d39d3cb3"): {},
- HexToAddress("0x3538a544021c07869c16b764424c5987409cba48"): {},
- HexToAddress("0xe187cf86c2274b1f16e8225a7da9a75aba4f1f5f"): {},
- HexToAddress("0x0000000000000000000000000000000000000011"): {},
- },
-}
diff --git a/common/constants.shared.go b/common/constants.shared.go
new file mode 100644
index 000000000000..0090e6be76fa
--- /dev/null
+++ b/common/constants.shared.go
@@ -0,0 +1,87 @@
+package common
+
+// Shared global ignoreSignerCheckBlockArray for all networks
+var ignoreSignerCheckBlockArray = map[uint64]struct{}{
+ 1032300: {},
+ 1033200: {},
+ 27307800: {},
+ 28270800: {},
+}
+
+// Shared global denylist for all networks
+var denylist = map[Address]struct{}{
+ HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd"): {},
+ HexToAddress("0x5ac26105b35ea8935be382863a70281ec7a985e9"): {},
+ HexToAddress("0x09c4f991a41e7ca0645d7dfbfee160b55e562ea4"): {},
+ HexToAddress("0xb3157bbc5b401a45d6f60b106728bb82ebaa585b"): {},
+ HexToAddress("0x741277a8952128d5c2ffe0550f5001e4c8247674"): {},
+ HexToAddress("0x10ba49c1caa97d74b22b3e74493032b180cebe01"): {},
+ HexToAddress("0x07048d51d9e6179578a6e3b9ee28cdc183b865e4"): {},
+ HexToAddress("0x4b899001d73c7b4ec404a771d37d9be13b8983de"): {},
+ HexToAddress("0x85cb320a9007f26b7652c19a2a65db1da2d0016f"): {},
+ HexToAddress("0x06869dbd0e3a2ea37ddef832e20fa005c6f0ca39"): {},
+ HexToAddress("0x82e48bc7e2c93d89125428578fb405947764ad7c"): {},
+ HexToAddress("0x1f9a78534d61732367cbb43fc6c89266af67c989"): {},
+ HexToAddress("0x7c3b1fa91df55ff7af0cad9e0399384dc5c6641b"): {},
+ HexToAddress("0x5888dc1ceb0ff632713486b9418e59743af0fd20"): {},
+ HexToAddress("0xa512fa1c735fc3cc635624d591dd9ea1ce339ca5"): {},
+ HexToAddress("0x0832517654c7b7e36b1ef45d76de70326b09e2c7"): {},
+ HexToAddress("0xca14e3c4c78bafb60819a78ff6e6f0f709d2aea7"): {},
+ HexToAddress("0x652ce195a23035114849f7642b0e06647d13e57a"): {},
+ HexToAddress("0x29a79f00f16900999d61b6e171e44596af4fb5ae"): {},
+ HexToAddress("0xf9fd1c2b0af0d91b0b6754e55639e3f8478dd04a"): {},
+ HexToAddress("0xb835710c9901d5fe940ef1b99ed918902e293e35"): {},
+ HexToAddress("0x04dd29ce5c253377a9a3796103ea0d9a9e514153"): {},
+ HexToAddress("0x2b4b56846eaf05c1fd762b5e1ac802efd0ab871c"): {},
+ HexToAddress("0x1d1f909f6600b23ce05004f5500ab98564717996"): {},
+ HexToAddress("0x0dfdcebf80006dc9ab7aae8c216b51c6b6759e86"): {},
+ HexToAddress("0x2b373890a28e5e46197fbc04f303bbfdd344056f"): {},
+ HexToAddress("0xa8a3ef3dc5d8e36aee76f3671ec501ec31e28254"): {},
+ HexToAddress("0x4f3d18136fe2b5665c29bdaf74591fc6625ef427"): {},
+ HexToAddress("0x175d728b0e0f1facb5822a2e0c03bde93596e324"): {},
+ HexToAddress("0xd575c2611984fcd79513b80ab94f59dc5bab4916"): {},
+ HexToAddress("0x0579337873c97c4ba051310236ea847f5be41bc0"): {},
+ HexToAddress("0xed12a519cc15b286920fc15fd86106b3e6a16218"): {},
+ HexToAddress("0x492d26d852a0a0a2982bb40ec86fe394488c419e"): {},
+ HexToAddress("0xce5c7635d02dc4e1d6b46c256cae6323be294a32"): {},
+ HexToAddress("0x8b94db158b5e78a6c032c7e7c9423dec62c8b11c"): {},
+ HexToAddress("0x0e7c48c085b6b0aa7ca6e4cbcc8b9a92dc270eb4"): {},
+ HexToAddress("0x206e6508462033ef8425edc6c10789d241d49acb"): {},
+ HexToAddress("0x7710e7b7682f26cb5a1202e1cff094fbf7777758"): {},
+ HexToAddress("0xcb06f949313b46bbf53b8e6b2868a0c260ff9385"): {},
+ HexToAddress("0xf884e43533f61dc2997c0e19a6eff33481920c00"): {},
+ HexToAddress("0x8b635ef2e4c8fe21fc2bda027eb5f371d6aa2fc1"): {},
+ HexToAddress("0x10f01a27cf9b29d02ce53497312b96037357a361"): {},
+ HexToAddress("0x693dd49b0ed70f162d733cf20b6c43dc2a2b4d95"): {},
+ HexToAddress("0xe0bec72d1c2a7a7fb0532cdfac44ebab9f6f41ee"): {},
+ HexToAddress("0xc8793633a537938cb49cdbbffd45428f10e45b64"): {},
+ HexToAddress("0x0d07a6cbbe9fa5c4f154e5623bfe47fb4d857d8e"): {},
+ HexToAddress("0xd4080b289da95f70a586610c38268d8d4cf1e4c4"): {},
+ HexToAddress("0x8bcfb0caf41f0aa1b548cae76dcdd02e33866a1b"): {},
+ HexToAddress("0xabfef22b92366d3074676e77ea911ccaabfb64c1"): {},
+ HexToAddress("0xcc4df7a32faf3efba32c9688def5ccf9fefe443d"): {},
+ HexToAddress("0x7ec1e48a582475f5f2b7448a86c4ea7a26ea36f8"): {},
+ HexToAddress("0xe3de67289080f63b0c2612844256a25bb99ac0ad"): {},
+ HexToAddress("0x3ba623300cf9e48729039b3c9e0dee9b785d636e"): {},
+ HexToAddress("0x402f2cfc9c8942f5e7a12c70c625d07a5d52fe29"): {},
+ HexToAddress("0xd62358d42afbde095a4ca868581d85f9adcc3d61"): {},
+ HexToAddress("0x3969f86acb733526cd61e3c6e3b4660589f32bc6"): {},
+ HexToAddress("0x67615413d7cdadb2c435a946aec713a9a9794d39"): {},
+ HexToAddress("0xfe685f43acc62f92ab01a8da80d76455d39d3cb3"): {},
+ HexToAddress("0x3538a544021c07869c16b764424c5987409cba48"): {},
+ HexToAddress("0xe187cf86c2274b1f16e8225a7da9a75aba4f1f5f"): {},
+ HexToAddress("0x0000000000000000000000000000000000000011"): {},
+}
+
+func IsIgnoreSignerCheckBlock(blockNumber uint64) bool {
+ _, ok := ignoreSignerCheckBlockArray[blockNumber]
+ return ok
+}
+
+func IsInDenylist(address *Address) bool {
+ if address == nil {
+ return false
+ }
+ _, ok := denylist[*address]
+ return ok
+}
diff --git a/common/constants.testnet.go b/common/constants.testnet.go
deleted file mode 100644
index 541681e4ef73..000000000000
--- a/common/constants.testnet.go
+++ /dev/null
@@ -1,114 +0,0 @@
-package common
-
-import (
- "math"
- "math/big"
-)
-
-var TestnetConstant = constant{
- chainID: 51,
- denylistHFNumber: 23779191,
- maxMasternodesV2: 15,
-
- tip2019Block: big.NewInt(1),
- tipSigning: big.NewInt(3000000),
- tipRandomize: big.NewInt(3464000),
- tipNoHalvingMNReward: big.NewInt(23779191), // hardfork no halving masternodes reward
- tipXDCX: big.NewInt(23779191),
- tipXDCXLending: big.NewInt(23779191),
- tipXDCXCancellationFee: big.NewInt(23779191),
- tipTRC21Fee: big.NewInt(23779191),
- tipIncreaseMasternodes: big.NewInt(5000000),
- blockNumberGas50x: big.NewInt(56828700), // Target 13rd Nov 2023
- TIPV2SwitchBlock: big.NewInt(56828700), // Target 13rd Nov 2023
- berlinBlock: big.NewInt(61290000), // Target 31st March 2024
- londonBlock: big.NewInt(61290000), // Target 31st March 2024
- mergeBlock: big.NewInt(61290000), // Target 31st March 2024
- shanghaiBlock: big.NewInt(61290000), // Target 31st March 2024
- tipXDCXMinerDisable: big.NewInt(61290000), // Target 31st March 2024
- tipXDCXReceiverDisable: big.NewInt(66825000), // Target 26 Aug 2024
- eip1559Block: big.NewInt(71550000), // Target 14th Feb 2025
- cancunBlock: big.NewInt(71551800),
- pragueBlock: big.NewInt(math.MaxInt64),
- osakaBlock: big.NewInt(math.MaxInt64),
- dynamicGasLimitBlock: big.NewInt(math.MaxInt64),
- tipUpgradeReward: big.NewInt(math.MaxInt64),
- tipUpgradePenalty: big.NewInt(math.MaxInt64),
- tipEpochHalving: big.NewInt(math.MaxInt64),
-
- trc21IssuerSMC: HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
- xdcxListingSMC: HexToAddress("0x14B2Bf043b9c31827A472CE4F94294fE9a6277e0"),
- relayerRegistrationSMC: HexToAddress("0xA1996F69f47ba14Cb7f661010A7C31974277958c"),
- lendingRegistrationSMC: HexToAddress("0x28d7fC2Cf5c18203aaCD7459EFC6Af0643C97bE8"),
-
- ignoreSignerCheckBlockArray: map[uint64]struct{}{
- 1032300: {},
- 1033200: {},
- 27307800: {},
- 28270800: {},
- },
-
- denylist: map[Address]struct{}{
- HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd"): {},
- HexToAddress("0x5ac26105b35ea8935be382863a70281ec7a985e9"): {},
- HexToAddress("0x09c4f991a41e7ca0645d7dfbfee160b55e562ea4"): {},
- HexToAddress("0xb3157bbc5b401a45d6f60b106728bb82ebaa585b"): {},
- HexToAddress("0x741277a8952128d5c2ffe0550f5001e4c8247674"): {},
- HexToAddress("0x10ba49c1caa97d74b22b3e74493032b180cebe01"): {},
- HexToAddress("0x07048d51d9e6179578a6e3b9ee28cdc183b865e4"): {},
- HexToAddress("0x4b899001d73c7b4ec404a771d37d9be13b8983de"): {},
- HexToAddress("0x85cb320a9007f26b7652c19a2a65db1da2d0016f"): {},
- HexToAddress("0x06869dbd0e3a2ea37ddef832e20fa005c6f0ca39"): {},
- HexToAddress("0x82e48bc7e2c93d89125428578fb405947764ad7c"): {},
- HexToAddress("0x1f9a78534d61732367cbb43fc6c89266af67c989"): {},
- HexToAddress("0x7c3b1fa91df55ff7af0cad9e0399384dc5c6641b"): {},
- HexToAddress("0x5888dc1ceb0ff632713486b9418e59743af0fd20"): {},
- HexToAddress("0xa512fa1c735fc3cc635624d591dd9ea1ce339ca5"): {},
- HexToAddress("0x0832517654c7b7e36b1ef45d76de70326b09e2c7"): {},
- HexToAddress("0xca14e3c4c78bafb60819a78ff6e6f0f709d2aea7"): {},
- HexToAddress("0x652ce195a23035114849f7642b0e06647d13e57a"): {},
- HexToAddress("0x29a79f00f16900999d61b6e171e44596af4fb5ae"): {},
- HexToAddress("0xf9fd1c2b0af0d91b0b6754e55639e3f8478dd04a"): {},
- HexToAddress("0xb835710c9901d5fe940ef1b99ed918902e293e35"): {},
- HexToAddress("0x04dd29ce5c253377a9a3796103ea0d9a9e514153"): {},
- HexToAddress("0x2b4b56846eaf05c1fd762b5e1ac802efd0ab871c"): {},
- HexToAddress("0x1d1f909f6600b23ce05004f5500ab98564717996"): {},
- HexToAddress("0x0dfdcebf80006dc9ab7aae8c216b51c6b6759e86"): {},
- HexToAddress("0x2b373890a28e5e46197fbc04f303bbfdd344056f"): {},
- HexToAddress("0xa8a3ef3dc5d8e36aee76f3671ec501ec31e28254"): {},
- HexToAddress("0x4f3d18136fe2b5665c29bdaf74591fc6625ef427"): {},
- HexToAddress("0x175d728b0e0f1facb5822a2e0c03bde93596e324"): {},
- HexToAddress("0xd575c2611984fcd79513b80ab94f59dc5bab4916"): {},
- HexToAddress("0x0579337873c97c4ba051310236ea847f5be41bc0"): {},
- HexToAddress("0xed12a519cc15b286920fc15fd86106b3e6a16218"): {},
- HexToAddress("0x492d26d852a0a0a2982bb40ec86fe394488c419e"): {},
- HexToAddress("0xce5c7635d02dc4e1d6b46c256cae6323be294a32"): {},
- HexToAddress("0x8b94db158b5e78a6c032c7e7c9423dec62c8b11c"): {},
- HexToAddress("0x0e7c48c085b6b0aa7ca6e4cbcc8b9a92dc270eb4"): {},
- HexToAddress("0x206e6508462033ef8425edc6c10789d241d49acb"): {},
- HexToAddress("0x7710e7b7682f26cb5a1202e1cff094fbf7777758"): {},
- HexToAddress("0xcb06f949313b46bbf53b8e6b2868a0c260ff9385"): {},
- HexToAddress("0xf884e43533f61dc2997c0e19a6eff33481920c00"): {},
- HexToAddress("0x8b635ef2e4c8fe21fc2bda027eb5f371d6aa2fc1"): {},
- HexToAddress("0x10f01a27cf9b29d02ce53497312b96037357a361"): {},
- HexToAddress("0x693dd49b0ed70f162d733cf20b6c43dc2a2b4d95"): {},
- HexToAddress("0xe0bec72d1c2a7a7fb0532cdfac44ebab9f6f41ee"): {},
- HexToAddress("0xc8793633a537938cb49cdbbffd45428f10e45b64"): {},
- HexToAddress("0x0d07a6cbbe9fa5c4f154e5623bfe47fb4d857d8e"): {},
- HexToAddress("0xd4080b289da95f70a586610c38268d8d4cf1e4c4"): {},
- HexToAddress("0x8bcfb0caf41f0aa1b548cae76dcdd02e33866a1b"): {},
- HexToAddress("0xabfef22b92366d3074676e77ea911ccaabfb64c1"): {},
- HexToAddress("0xcc4df7a32faf3efba32c9688def5ccf9fefe443d"): {},
- HexToAddress("0x7ec1e48a582475f5f2b7448a86c4ea7a26ea36f8"): {},
- HexToAddress("0xe3de67289080f63b0c2612844256a25bb99ac0ad"): {},
- HexToAddress("0x3ba623300cf9e48729039b3c9e0dee9b785d636e"): {},
- HexToAddress("0x402f2cfc9c8942f5e7a12c70c625d07a5d52fe29"): {},
- HexToAddress("0xd62358d42afbde095a4ca868581d85f9adcc3d61"): {},
- HexToAddress("0x3969f86acb733526cd61e3c6e3b4660589f32bc6"): {},
- HexToAddress("0x67615413d7cdadb2c435a946aec713a9a9794d39"): {},
- HexToAddress("0xfe685f43acc62f92ab01a8da80d76455d39d3cb3"): {},
- HexToAddress("0x3538a544021c07869c16b764424c5987409cba48"): {},
- HexToAddress("0xe187cf86c2274b1f16e8225a7da9a75aba4f1f5f"): {},
- HexToAddress("0x0000000000000000000000000000000000000011"): {},
- },
-}
diff --git a/common/constants_test.go b/common/constants_test.go
new file mode 100644
index 000000000000..b3fcbdc45f81
--- /dev/null
+++ b/common/constants_test.go
@@ -0,0 +1,33 @@
+package common
+
+import "testing"
+
+func TestIsIgnoreSignerCheckBlock(t *testing.T) {
+ t.Parallel()
+
+ if !IsIgnoreSignerCheckBlock(1032300) {
+ t.Fatal("expected block 1032300 to be in ignore signer check list")
+ }
+
+ if IsIgnoreSignerCheckBlock(1) {
+ t.Fatal("expected block 1 to not be in ignore signer check list")
+ }
+}
+
+func TestIsInDenylist(t *testing.T) {
+ t.Parallel()
+
+ inList := HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd")
+ if !IsInDenylist(&inList) {
+ t.Fatal("expected known address to be in denylist")
+ }
+
+ notInList := HexToAddress("0x0000000000000000000000000000000000000001")
+ if IsInDenylist(¬InList) {
+ t.Fatal("expected unknown address to not be in denylist")
+ }
+
+ if IsInDenylist(nil) {
+ t.Fatal("expected nil address to not be in denylist")
+ }
+}
diff --git a/common/gas.go b/common/gas.go
index 7f1135ceeaca..f7021b49e2d6 100644
--- a/common/gas.go
+++ b/common/gas.go
@@ -6,32 +6,29 @@ var MinGasPrice50x = big.NewInt(12500000000)
var GasPrice50x = big.NewInt(12500000000)
var BaseFee = big.NewInt(12500000000)
-func GetGasFee(blockNumber, gas uint64) *big.Int {
+// GetGasFee returns the effective fee for the given block and gas usage.
+// Callers must ensure gas50xBlock >= tipTRC21FeeBlock when both values are configured.
+func GetGasFee(blockNumber, gas uint64, tipTRC21FeeBlock, gas50xBlock *big.Int) *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)
- } else {
- fee = fee.Mul(fee, TRC21GasPriceBefore)
+ if gas50xBlock != nil && blockNumber >= gas50xBlock.Uint64() {
+ return fee.Mul(fee, GasPrice50x)
}
-
- return fee
+ if tipTRC21FeeBlock != nil && blockNumber > tipTRC21FeeBlock.Uint64() {
+ return fee.Mul(fee, TRC21GasPrice)
+ }
+ return fee.Mul(fee, TRC21GasPriceBefore)
}
-func GetGasPrice(number *big.Int) *big.Int {
- if number == nil || number.Cmp(BlockNumberGas50x) < 0 {
- return new(big.Int).Set(TRC21GasPrice)
- } else {
+func GetGasPrice(number, gas50xBlock *big.Int) *big.Int {
+ if number != nil && gas50xBlock != nil && number.Cmp(gas50xBlock) >= 0 {
return new(big.Int).Set(GasPrice50x)
}
+ return new(big.Int).Set(TRC21GasPrice)
}
-func GetMinGasPrice(number *big.Int) *big.Int {
- if number == nil || number.Cmp(BlockNumberGas50x) < 0 {
- return new(big.Int).Set(MinGasPrice)
- } else {
+func GetMinGasPrice(number, gas50xBlock *big.Int) *big.Int {
+ if number != nil && gas50xBlock != nil && number.Cmp(gas50xBlock) >= 0 {
return new(big.Int).Set(MinGasPrice50x)
}
+ return new(big.Int).Set(MinGasPrice)
}
diff --git a/common/gas_test.go b/common/gas_test.go
new file mode 100644
index 000000000000..b1a1d8cc8db0
--- /dev/null
+++ b/common/gas_test.go
@@ -0,0 +1,38 @@
+package common
+
+import (
+ "math/big"
+ "testing"
+)
+
+func TestGetGasFeeUsesGas50xBlock(t *testing.T) {
+ gas50xBlock := big.NewInt(100)
+ tipTRC21FeeBlock := big.NewInt(50)
+
+ beforeFork := GetGasFee(99, 2, tipTRC21FeeBlock, gas50xBlock)
+ if want := new(big.Int).Mul(big.NewInt(2), TRC21GasPrice); beforeFork.Cmp(want) != 0 {
+ t.Fatalf("unexpected fee before gas50x fork: have %v want %v", beforeFork, want)
+ }
+
+ afterFork := GetGasFee(100, 2, tipTRC21FeeBlock, gas50xBlock)
+ if want := new(big.Int).Mul(big.NewInt(2), GasPrice50x); afterFork.Cmp(want) != 0 {
+ t.Fatalf("unexpected fee after gas50x fork: have %v want %v", afterFork, want)
+ }
+}
+
+func TestGetGasPriceAndMinGasPriceUseGas50xBlock(t *testing.T) {
+ gas50xBlock := big.NewInt(100)
+
+ if got := GetGasPrice(big.NewInt(99), gas50xBlock); got.Cmp(TRC21GasPrice) != 0 {
+ t.Fatalf("unexpected gas price before gas50x fork: have %v want %v", got, TRC21GasPrice)
+ }
+ if got := GetGasPrice(big.NewInt(100), gas50xBlock); got.Cmp(GasPrice50x) != 0 {
+ t.Fatalf("unexpected gas price after gas50x fork: have %v want %v", got, GasPrice50x)
+ }
+ if got := GetMinGasPrice(big.NewInt(99), gas50xBlock); got.Cmp(MinGasPrice) != 0 {
+ t.Fatalf("unexpected min gas price before gas50x fork: have %v want %v", got, MinGasPrice)
+ }
+ if got := GetMinGasPrice(big.NewInt(100), gas50xBlock); got.Cmp(MinGasPrice50x) != 0 {
+ t.Fatalf("unexpected min gas price after gas50x fork: have %v want %v", got, MinGasPrice50x)
+ }
+}
diff --git a/consensus/XDPoS/api.go b/consensus/XDPoS/api.go
index 3bace2c902b6..6dfdacebdf4d 100644
--- a/consensus/XDPoS/api.go
+++ b/consensus/XDPoS/api.go
@@ -16,6 +16,7 @@
package XDPoS
import (
+ "context"
"encoding/base64"
"encoding/json"
"errors"
@@ -31,6 +32,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/core/types"
+ "github.com/XinFinOrg/XDPoSChain/internal/configapi"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/rlp"
@@ -133,6 +135,28 @@ type PoolStatus struct {
SyncInfo map[string]SyncInfoTypes `json:"syncInfo"`
}
+type configBackend struct {
+ chain consensus.ChainReader
+}
+
+func (b configBackend) HeaderByNumber(_ context.Context, number rpc.BlockNumber) (*types.Header, error) {
+ if number == rpc.LatestBlockNumber {
+ return b.chain.CurrentHeader(), nil
+ }
+ if number.Int64() < 0 {
+ return nil, fmt.Errorf("invalid block number %d", number.Int64())
+ }
+ return b.chain.GetHeaderByNumber(uint64(number.Int64())), nil
+}
+
+func (b configBackend) CurrentHeader() *types.Header {
+ return b.chain.CurrentHeader()
+}
+
+func (b configBackend) ChainConfig() *params.ChainConfig {
+ return b.chain.Config()
+}
+
// GetSnapshot retrieves the state snapshot at a given block.
func (api *API) GetSnapshot(number *rpc.BlockNumber) (*utils.PublicApiSnapshot, error) {
// Retrieve the requested block number (or current if none requested)
@@ -371,17 +395,22 @@ func (api *API) GetV2BlockByHash(blockHash common.Hash) *V2BlockInfo {
func (api *API) NetworkInformation() NetworkInformation {
info := NetworkInformation{}
- info.NetworkId = api.chain.Config().ChainID
+ config := api.chain.Config()
+ info.NetworkId = config.ChainID
info.XDCValidatorAddress = common.MasternodeVotingSMCBinary
- info.LendingAddress = common.LendingRegistrationSMC
- info.RelayerRegistrationAddress = common.RelayerRegistrationSMC
- info.XDCXListingAddress = common.XDCXListingSMC
- info.XDCZAddress = common.TRC21IssuerSMC
+ info.LendingAddress = config.LendingRegistrationSMC
+ info.RelayerRegistrationAddress = config.RelayerRegistrationSMC
+ info.XDCXListingAddress = config.XDCXListingSMC
+ info.XDCZAddress = config.TRC21IssuerSMC
info.ConsensusConfigs = *api.XDPoS.config
return info
}
+func (api *API) GetConfig(ctx context.Context) (*configapi.ConfigResponse, error) {
+ return configapi.Build(ctx, configBackend{chain: api.chain})
+}
+
/*
An API exclusively for V2 consensus, designed to assist in troubleshooting miners by identifying who mined during their allocated term.
*/
diff --git a/consensus/XDPoS/api_test.go b/consensus/XDPoS/api_test.go
index 2bff765d4e4a..5faf739cbe30 100644
--- a/consensus/XDPoS/api_test.go
+++ b/consensus/XDPoS/api_test.go
@@ -1,15 +1,97 @@
package XDPoS
import (
+ "context"
"math/big"
"testing"
"github.com/XinFinOrg/XDPoSChain/common"
+ "github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
+ "github.com/XinFinOrg/XDPoSChain/core/forkid"
"github.com/XinFinOrg/XDPoSChain/core/types"
+ "github.com/XinFinOrg/XDPoSChain/params"
+ "github.com/XinFinOrg/XDPoSChain/params/forks"
+ "github.com/XinFinOrg/XDPoSChain/rpc"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
+type configChainMock struct {
+ genesis *types.Header
+ current *types.Header
+ config *params.ChainConfig
+}
+
+func newConfigChainMock() *configChainMock {
+ return newConfigChainMockWithCurrent(1500)
+}
+
+func newConfigChainMockWithCurrent(current uint64) *configChainMock {
+ return &configChainMock{
+ genesis: &types.Header{Number: big.NewInt(0)},
+ current: &types.Header{Number: new(big.Int).SetUint64(current), BaseFee: big.NewInt(10)},
+ config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(42),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ Eip1559Block: big.NewInt(1000),
+ XDPoS: ¶ms.XDPoSConfig{V2: ¶ms.V2{SwitchBlock: big.NewInt(1500)}},
+ },
+ }
+}
+
+func (m *configChainMock) Config() *params.ChainConfig { return m.config }
+
+func (m *configChainMock) CurrentHeader() *types.Header { return m.current }
+
+func (m *configChainMock) GetHeader(hash common.Hash, number uint64) *types.Header {
+ header := m.GetHeaderByNumber(number)
+ if header != nil && header.Hash() == hash {
+ return header
+ }
+ return nil
+}
+
+func (m *configChainMock) GetHeaderByNumber(number uint64) *types.Header {
+ switch number {
+ case 0:
+ return m.genesis
+ case m.current.Number.Uint64():
+ return m.current
+ default:
+ return nil
+ }
+}
+
+func (m *configChainMock) GetHeaderByHash(hash common.Hash) *types.Header {
+ if m.genesis.Hash() == hash {
+ return m.genesis
+ }
+ if m.current.Hash() == hash {
+ return m.current
+ }
+ return nil
+}
+
+func (m *configChainMock) GetBlock(hash common.Hash, number uint64) *types.Block {
+ header := m.GetHeader(hash, number)
+ if header == nil {
+ return nil
+ }
+ return types.NewBlockWithHeader(header)
+}
+
+var _ consensus.ChainReader = (*configChainMock)(nil)
+
func TestCalculateSignersVote(t *testing.T) {
info := make(map[string]SignerTypes)
votes := utils.NewPool()
@@ -69,3 +151,43 @@ func TestCalculateSignersTimeout(t *testing.T) {
calculateSigners(info, timeouts.Get(), masternodes)
assert.Equal(t, info["10:450"].CurrentNumber, 2)
}
+
+func TestAPIGetConfig(t *testing.T) {
+ chain := newConfigChainMockWithCurrent(1500)
+ api := &API{chain: chain}
+
+ resp, err := api.GetConfig(context.Background())
+ require.NoError(t, err)
+ require.NotNil(t, resp)
+ require.NotNil(t, resp.Current)
+ require.Equal(t, uint64(1500), resp.Current.ActivationBlock)
+ require.Contains(t, resp.Current.ActiveForks, forks.XDPoSV2.String())
+ require.Nil(t, resp.Next)
+ require.Nil(t, resp.Last)
+ require.Equal(t, chain.config.ChainID, (*big.Int)(resp.Current.ChainId))
+ forkID := forkid.NewID(chain.config, types.NewBlockWithHeader(chain.genesis), resp.Current.ActivationBlock).Hash
+ require.Equal(t, forkID[:], []byte(resp.Current.ForkId))
+ require.NotNil(t, configBackend{chain: chain}.CurrentHeader())
+ genesis, err := configBackend{chain: chain}.HeaderByNumber(context.Background(), rpc.BlockNumber(0))
+ require.NoError(t, err)
+ require.NotNil(t, genesis)
+}
+
+func TestAPIGetConfig_BeforeXDPoSV2Switch(t *testing.T) {
+ chain := newConfigChainMockWithCurrent(1400)
+ api := &API{chain: chain}
+
+ resp, err := api.GetConfig(context.Background())
+ require.NoError(t, err)
+ require.NotNil(t, resp)
+ require.NotNil(t, resp.Current)
+ require.NotNil(t, resp.Next)
+ require.NotNil(t, resp.Last)
+
+ require.Equal(t, uint64(1000), resp.Current.ActivationBlock)
+ require.NotContains(t, resp.Current.ActiveForks, forks.XDPoSV2.String())
+
+ require.Equal(t, uint64(1500), resp.Next.ActivationBlock)
+ require.Contains(t, resp.Next.ActiveForks, forks.XDPoSV2.String())
+ require.Equal(t, uint64(1500), resp.Last.ActivationBlock)
+}
diff --git a/consensus/XDPoS/engines/engine_v1/engine.go b/consensus/XDPoS/engines/engine_v1/engine.go
index cfa11cdf4d54..da916c7b88f4 100644
--- a/consensus/XDPoS/engines/engine_v1/engine.go
+++ b/consensus/XDPoS/engines/engine_v1/engine.go
@@ -792,7 +792,7 @@ func (x *XDPoS_v1) UpdateMasternodes(chain consensus.ChainReader, header *types.
// check if block number is increase ms checkpoint
if x.chainConfig.IsTIPIncreaseMasternodes(header.Number) || (x.config.V2.SwitchBlock != nil && header.Number.Cmp(x.config.V2.SwitchBlock) == 1) {
// using new masterndoes
- maxMasternodes = common.MaxMasternodesV2
+ maxMasternodes = x.chainConfig.XDPoS.MaxMasternodesV2
} else {
// using old masterndoes
maxMasternodes = common.MaxMasternodes
diff --git a/consensus/XDPoS/engines/engine_v1/utils_test.go b/consensus/XDPoS/engines/engine_v1/utils_test.go
index 568bbd92099f..f9fb9b5d71cb 100644
--- a/consensus/XDPoS/engines/engine_v1/utils_test.go
+++ b/consensus/XDPoS/engines/engine_v1/utils_test.go
@@ -23,6 +23,7 @@ func TestGetM1M2FromCheckpointHeader(t *testing.T) {
}
epoch := uint64(900)
config := ¶ms.ChainConfig{
+ TIPRandomizeBlock: big.NewInt(3464000),
XDPoS: ¶ms.XDPoSConfig{
Epoch: epoch,
},
diff --git a/consensus/tests/engine_v1_tests/helper.go b/consensus/tests/engine_v1_tests/helper.go
index 1f887437bd30..3d825431aa82 100644
--- a/consensus/tests/engine_v1_tests/helper.go
+++ b/consensus/tests/engine_v1_tests/helper.go
@@ -74,10 +74,13 @@ func RandStringBytes(n int) string {
func getCommonBackend(t *testing.T, chainConfig *params.ChainConfig) *backends.SimulatedBackend {
// initial helper backend
contractBackendForSC := backends.NewXDCSimulatedBackend(types.GenesisAlloc{
- voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
+ voterAddr: {Balance: new(big.Int).SetUint64(1000000000000000000)},
}, 10000000, chainConfig)
- transactOpts := bind.NewKeyedTransactor(voterKey)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(voterKey, chainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
var candidates []common.Address
var caps []*big.Int
@@ -225,8 +228,40 @@ func GetCandidateFromCurrentSmartContract(backend bind.ContractBackend, t *testi
return ms
}
+func legacyV1TestChainConfig(chainConfig *params.ChainConfig) *params.ChainConfig {
+ if chainConfig == nil {
+ return nil
+ }
+ legacy := *chainConfig
+ futureForkBlock := big.NewInt(1_000_000_000)
+ legacy.TIP2019Block = new(big.Int).Set(futureForkBlock)
+ legacy.PetersburgBlock = new(big.Int).Set(futureForkBlock)
+ legacy.IstanbulBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPSigningBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPRandomizeBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPIncreaseMasternodesBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPNoHalvingMNRewardBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPXDCXBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPXDCXLendingBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPXDCXCancellationFeeBlock = new(big.Int).Set(futureForkBlock)
+ legacy.BerlinBlock = new(big.Int).Set(futureForkBlock)
+ legacy.LondonBlock = new(big.Int).Set(futureForkBlock)
+ legacy.MergeBlock = new(big.Int).Set(futureForkBlock)
+ legacy.ShanghaiBlock = new(big.Int).Set(futureForkBlock)
+ legacy.Eip1559Block = new(big.Int).Set(futureForkBlock)
+ legacy.CancunBlock = new(big.Int).Set(futureForkBlock)
+ legacy.PragueBlock = new(big.Int).Set(futureForkBlock)
+ legacy.OsakaBlock = new(big.Int).Set(futureForkBlock)
+ legacy.DynamicGasLimitBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPUpgradeRewardBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPUpgradePenaltyBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPEpochHalvingBlock = new(big.Int).Set(futureForkBlock)
+ return &legacy
+}
+
// V1 consensus engine
func PrepareXDCTestBlockChain(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig) (*core.BlockChain, *backends.SimulatedBackend, *types.Block, common.Address, func(account accounts.Account, hash []byte) ([]byte, error)) {
+ chainConfig = legacyV1TestChainConfig(chainConfig)
// Preparation
var err error
// Authorise
@@ -356,6 +391,9 @@ func createBlockFromHeader(bc *core.BlockChain, customHeader *types.Header, txs
Validators: customHeader.Validators,
Penalties: customHeader.Penalties,
}
+ if config != nil && config.IsEIP1559(header.Number) {
+ header.BaseFee = new(big.Int).Set(common.BaseFee)
+ }
var block *types.Block
if len(txs) == 0 {
block = types.NewBlockWithHeader(&header)
diff --git a/consensus/tests/engine_v2_tests/authorised_masternode_test.go b/consensus/tests/engine_v2_tests/authorised_masternode_test.go
index 9ea21232ec4c..5225ac2e23a6 100644
--- a/consensus/tests/engine_v2_tests/authorised_masternode_test.go
+++ b/consensus/tests/engine_v2_tests/authorised_masternode_test.go
@@ -109,7 +109,8 @@ func TestIsYourTurnConsensusV2CrossConfig(t *testing.T) {
// after new mine period
secondMinePeriod := blockchain.Config().XDPoS.V2.CurrentConfig.MinePeriod
- time.Sleep(time.Duration(secondMinePeriod-firstMinePeriod) * time.Second)
+ // YourTurn uses Unix-second granularity; add a small buffer to avoid edge-time flakiness.
+ time.Sleep(time.Duration(secondMinePeriod-firstMinePeriod+1) * time.Second)
isYourTurn, err = adaptor.YourTurn(blockchain, currentBlockHeader, common.HexToAddress("xdc703c4b2bD70c169f5717101CaeE543299Fc946C7"))
assert.Nil(t, err)
assert.True(t, isYourTurn)
diff --git a/consensus/tests/engine_v2_tests/helper.go b/consensus/tests/engine_v2_tests/helper.go
index 284b3f39dba1..9d6e4501bbb1 100644
--- a/consensus/tests/engine_v2_tests/helper.go
+++ b/consensus/tests/engine_v2_tests/helper.go
@@ -133,10 +133,13 @@ func voteTX(gasLimit uint64, nonce uint64, addr string) (*types.Transaction, err
func getCommonBackend(t *testing.T, chainConfig *params.ChainConfig) *backends.SimulatedBackend {
// initial helper backend
contractBackendForSC := backends.NewXDCSimulatedBackend(types.GenesisAlloc{
- voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
+ voterAddr: {Balance: new(big.Int).SetUint64(1000000000000000000)},
}, 10000000, chainConfig)
- transactOpts := bind.NewKeyedTransactor(voterKey)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(voterKey, chainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
var candidates []common.Address
var caps []*big.Int
@@ -209,10 +212,13 @@ func getMultiCandidatesBackend(t *testing.T, chainConfig *params.ChainConfig, n
assert.GreaterOrEqual(t, n, 4)
// initial helper backend, give a very large gas limit
contractBackendForSC := backends.NewXDCSimulatedBackend(types.GenesisAlloc{
- voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
+ voterAddr: {Balance: new(big.Int).SetUint64(1000000000000000000)},
}, 1000000000, chainConfig)
- transactOpts := bind.NewKeyedTransactor(voterKey)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(voterKey, chainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
var candidates []common.Address
var caps []*big.Int
@@ -285,10 +291,13 @@ func getMultiCandidatesBackend(t *testing.T, chainConfig *params.ChainConfig, n
func getProtectorObserverBackend(t *testing.T, chainConfig *params.ChainConfig) *backends.SimulatedBackend {
// initial helper backend
contractBackendForSC := backends.NewXDCSimulatedBackend(types.GenesisAlloc{
- voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
+ voterAddr: {Balance: new(big.Int).SetUint64(1000000000000000000)},
}, 10000000, chainConfig)
- transactOpts := bind.NewKeyedTransactor(voterKey)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(voterKey, chainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
var candidates []common.Address
var caps []*big.Int
@@ -427,6 +436,30 @@ func GetCandidateFromCurrentSmartContract(backend bind.ContractBackend, t *testi
return ms
}
+func legacyExecutionConfigForV2Tests(chainConfig *params.ChainConfig) *params.ChainConfig {
+ if chainConfig == nil {
+ return nil
+ }
+ legacy := *chainConfig
+ futureForkBlock := big.NewInt(1_000_000_000)
+ legacy.PetersburgBlock = new(big.Int).Set(futureForkBlock)
+ legacy.IstanbulBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPIncreaseMasternodesBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPXDCXBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPXDCXLendingBlock = new(big.Int).Set(futureForkBlock)
+ legacy.TIPXDCXCancellationFeeBlock = new(big.Int).Set(futureForkBlock)
+ legacy.BerlinBlock = new(big.Int).Set(futureForkBlock)
+ legacy.LondonBlock = new(big.Int).Set(futureForkBlock)
+ legacy.MergeBlock = new(big.Int).Set(futureForkBlock)
+ legacy.ShanghaiBlock = new(big.Int).Set(futureForkBlock)
+ legacy.Eip1559Block = new(big.Int).Set(futureForkBlock)
+ legacy.CancunBlock = new(big.Int).Set(futureForkBlock)
+ legacy.PragueBlock = new(big.Int).Set(futureForkBlock)
+ legacy.OsakaBlock = new(big.Int).Set(futureForkBlock)
+ legacy.DynamicGasLimitBlock = new(big.Int).Set(futureForkBlock)
+ return &legacy
+}
+
type ForkedBlockOptions struct {
numOfForkedBlocks *int
forkedRoundDifference *int // Minimum is 1
@@ -435,6 +468,7 @@ type ForkedBlockOptions struct {
// V2 consensus engine
func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig, forkedBlockOptions *ForkedBlockOptions) (*core.BlockChain, *backends.SimulatedBackend, *types.Block, common.Address, func(account accounts.Account, hash []byte) ([]byte, error), *types.Block) {
+ chainConfig = legacyExecutionConfigForV2Tests(chainConfig)
// Preparation
var err error
signer, signFn, err := backends.SimulateWalletAddressAndSignFn()
@@ -526,6 +560,7 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
// V2 consensus engine, compared to PrepareXDCTestBlockChainForV2Engine: (1) no forking (2) add penalty
func PrepareXDCTestBlockChainWithPenaltyForV2Engine(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig) (*core.BlockChain, *backends.SimulatedBackend, *types.Block, common.Address, func(account accounts.Account, hash []byte) ([]byte, error)) {
+ chainConfig = legacyExecutionConfigForV2Tests(chainConfig)
// Preparation
var err error
signer, signFn, err := backends.SimulateWalletAddressAndSignFn()
@@ -582,6 +617,7 @@ func PrepareXDCTestBlockChainWithPenaltyForV2Engine(t *testing.T, numOfBlocks in
// V2 consensus engine, compared to PrepareXDCTestBlockChainForV2Engine: (1) no forking (2) add penalty
func PrepareXDCTestBlockChainWithPenaltyCustomized(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig, penaltyOrNot []bool) (*core.BlockChain, *backends.SimulatedBackend, *types.Block, common.Address, func(account accounts.Account, hash []byte) ([]byte, error)) {
+ chainConfig = legacyExecutionConfigForV2Tests(chainConfig)
// Preparation
var err error
signer, signFn, err := backends.SimulateWalletAddressAndSignFn()
@@ -645,6 +681,7 @@ func PrepareXDCTestBlockChainWithPenaltyCustomized(t *testing.T, numOfBlocks int
// V2 consensus engine, compared to PrepareXDCTestBlockChainForV2Engine: (1) no forking (2) 128 masternode candidates
func PrepareXDCTestBlockChainWith128Candidates(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig) (*core.BlockChain, *backends.SimulatedBackend, *types.Block, common.Address, func(account accounts.Account, hash []byte) ([]byte, error)) {
+ chainConfig = legacyExecutionConfigForV2Tests(chainConfig)
// Preparation
var err error
signer, signFn, err := backends.SimulateWalletAddressAndSignFn()
@@ -709,6 +746,7 @@ func PrepareXDCTestBlockChainWith128Candidates(t *testing.T, numOfBlocks int, ch
// V2 consensus engine
func PrepareXDCTestBlockChainWithProtectorObserver(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig) (*core.BlockChain, *backends.SimulatedBackend, *types.Block, common.Address, func(account accounts.Account, hash []byte) ([]byte, error)) {
+ chainConfig = legacyExecutionConfigForV2Tests(chainConfig)
// Preparation
var err error
signer, signFn, err := backends.SimulateWalletAddressAndSignFn()
@@ -888,6 +926,9 @@ func createBlockFromHeader(bc *core.BlockChain, customHeader *types.Header, txs
Validators: customHeader.Validators,
Penalties: customHeader.Penalties,
}
+ if config != nil && config.IsEIP1559(header.Number) {
+ header.BaseFee = new(big.Int).Set(common.BaseFee)
+ }
var block *types.Block
if len(txs) == 0 {
// Sign all the things and seal it
diff --git a/consensus/tests/engine_v2_tests/penalty_test.go b/consensus/tests/engine_v2_tests/penalty_test.go
index 7658d57d4c7d..2eb20423f500 100644
--- a/consensus/tests/engine_v2_tests/penalty_test.go
+++ b/consensus/tests/engine_v2_tests/penalty_test.go
@@ -162,19 +162,26 @@ func TestGetPenalties(t *testing.T) {
// but if it does not stays enough, it will still be penalty.
func TestHookPenaltyParolee(t *testing.T) {
skipLongInShortMode(t)
- // set upgrade number to 0
- backup := common.TipUpgradePenalty
- common.TipUpgradePenalty = big.NewInt(0)
+ b, err := json.Marshal(params.TestXDPoSMockChainConfig)
+ assert.Nil(t, err)
- config := params.TestXDPoSMockChainConfig
- blockchain, _, _, signer, signFn := PrepareXDCTestBlockChainWithPenaltyForV2Engine(t, int(config.XDPoS.Epoch)*4, config)
+ var config params.ChainConfig
+ err = json.Unmarshal(b, &config)
+ assert.Nil(t, err)
+ config.TIPUpgradePenaltyBlock = big.NewInt(0)
+ b, err = json.Marshal(config)
+ assert.Nil(t, err)
+ err = json.Unmarshal(b, &config)
+ assert.Nil(t, err)
+
+ blockchain, _, _, signer, signFn := PrepareXDCTestBlockChainWithPenaltyForV2Engine(t, int(config.XDPoS.Epoch)*4, &config)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
- hooks.AttachConsensusV2Hooks(adaptor, blockchain, config)
+ hooks.AttachConsensusV2Hooks(adaptor, blockchain, &config)
assert.NotNil(t, adaptor.EngineV2.HookPenalty)
var extraField types.ExtraFields_v2
// 901 is the first v2 block
header901 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch + 1)
- err := utils.DecodeBytesExtraFields(header901.Extra, &extraField)
+ err = utils.DecodeBytesExtraFields(header901.Extra, &extraField)
assert.Nil(t, err)
masternodes := adaptor.GetMasternodesFromCheckpointHeader(header901)
assert.Equal(t, 5, len(masternodes))
@@ -211,7 +218,6 @@ func TestHookPenaltyParolee(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, 1, len(penalty))
- common.TipUpgradePenalty = backup
}
// TestHookPenaltyParoleePerformance tests penalty hook performance
@@ -225,10 +231,11 @@ func TestHookPenaltyParoleePerformance(t *testing.T) {
err = json.Unmarshal([]byte(configString), &config)
assert.Nil(t, err)
config.XDPoS.V2.AllConfigs[900].LimitPenaltyEpoch = 4
-
- // set upgrade number to 0
- backup := common.TipUpgradePenalty
- common.TipUpgradePenalty = big.NewInt(0)
+ config.TIPUpgradePenaltyBlock = big.NewInt(0)
+ b, err = json.Marshal(config)
+ assert.Nil(t, err)
+ err = json.Unmarshal(b, &config)
+ assert.Nil(t, err)
// 900 1800 2700 3600(not) 4500 5400 has penalty except 3600
penaltyOrNot := []bool{true, true, true, false, true, true}
@@ -261,5 +268,4 @@ func TestHookPenaltyParoleePerformance(t *testing.T) {
// miner (coinbase) is not parolee since one epoch it is not penalty. so it is in penalty. plus another one, total 2.
assert.Equal(t, 2, len(penalty))
- common.TipUpgradePenalty = backup
}
diff --git a/consensus/tests/engine_v2_tests/reward_test.go b/consensus/tests/engine_v2_tests/reward_test.go
index 51eb0f3aa8de..6b905f6a8819 100644
--- a/consensus/tests/engine_v2_tests/reward_test.go
+++ b/consensus/tests/engine_v2_tests/reward_test.go
@@ -179,9 +179,11 @@ func TestHookRewardAfterUpgrade(t *testing.T) {
// set switch to 1800, so that it covers 901-1799, 1800-2700 two epochs
config.XDPoS.V2.SwitchBlock.SetUint64(1800)
config.XDPoS.V2.SwitchEpoch = 2
- // set upgrade number to 0
- backup := common.TIPUpgradeReward
- common.TIPUpgradeReward = big.NewInt(0)
+ config.TIPUpgradeRewardBlock = big.NewInt(0)
+ b, err = json.Marshal(config)
+ assert.Nil(t, err)
+ err = json.Unmarshal(b, &config)
+ assert.Nil(t, err)
blockchain, _, _, signer, signFn := PrepareXDCTestBlockChainWithProtectorObserver(t, int(config.XDPoS.Epoch)*3+10, &config)
@@ -312,7 +314,6 @@ func TestHookRewardAfterUpgrade(t *testing.T) {
totalBurned := statedb.GetPostBurned(epochNum).Big().Int64()
// since no EIP 1559, so no burned
assert.Zero(t, totalBurned, "statedb records wrong total burned")
- common.TIPUpgradeReward = backup
}
func TestFinalizeAfterUpgrade(t *testing.T) {
@@ -327,9 +328,11 @@ func TestFinalizeAfterUpgrade(t *testing.T) {
// set switch to 1800, so that it covers 901-1799, 1800-2700 two epochs
config.XDPoS.V2.SwitchBlock.SetUint64(1800)
config.XDPoS.V2.SwitchEpoch = 2
- // set upgrade number to 0
- backup := common.TIPUpgradeReward
- common.TIPUpgradeReward = big.NewInt(0)
+ config.TIPUpgradeRewardBlock = big.NewInt(0)
+ b, err = json.Marshal(config)
+ assert.Nil(t, err)
+ err = json.Unmarshal(b, &config)
+ assert.Nil(t, err)
blockchain, _, _, signer, signFn := PrepareXDCTestBlockChainWithProtectorObserver(t, int(config.XDPoS.Epoch)*3+10, &config)
@@ -381,7 +384,6 @@ func TestFinalizeAfterUpgrade(t *testing.T) {
minted := statedbAfterFinalize.GetPostMinted(epochNum)
assert.False(t, minted.IsZero())
- common.TIPUpgradeReward = backup
}
func TestRewardHalvingVanishing(t *testing.T) {
diff --git a/consensus/tests/engine_v2_tests/verify_header_test.go b/consensus/tests/engine_v2_tests/verify_header_test.go
index 0ae2066eda39..4f444b523d1a 100644
--- a/consensus/tests/engine_v2_tests/verify_header_test.go
+++ b/consensus/tests/engine_v2_tests/verify_header_test.go
@@ -469,12 +469,12 @@ func TestShouldVerifyHeadersEvenIfParentsNotYetWrittenIntoDB(t *testing.T) {
// Create block 911 but don't write into DB
blockNumber := 911
roundNumber := int64(blockNumber) - config.XDPoS.V2.SwitchBlock.Int64()
- block911 := CreateBlock(blockchain, &config, block910, blockNumber, roundNumber, signer.Hex(), signer, signFn, nil, nil, "")
+ block911 := CreateBlock(blockchain, blockchain.Config(), block910, blockNumber, roundNumber, signer.Hex(), signer, signFn, nil, nil, "")
// Create block 912 and not write into DB as well
blockNumber = 912
roundNumber = int64(blockNumber) - config.XDPoS.V2.SwitchBlock.Int64()
- block912 := CreateBlock(blockchain, &config, block911, blockNumber, roundNumber, signer.Hex(), signer, signFn, nil, nil, "")
+ block912 := CreateBlock(blockchain, blockchain.Config(), block911, blockNumber, roundNumber, signer.Hex(), signer, signFn, nil, nil, "")
headersTobeVerified = append(headersTobeVerified, block910.Header(), block911.Header(), block912.Header())
// Randomly set full verify
@@ -561,7 +561,7 @@ func TestShouldVerifyPureV2EpochSwitchHeadersEvenIfParentNotYetWrittenIntoDB(t *
block1799 := CreateBlock(
blockchain,
- &config,
+ blockchain.Config(),
block1798,
1799,
int64(1799)-config.XDPoS.V2.SwitchBlock.Int64(),
@@ -574,7 +574,7 @@ func TestShouldVerifyPureV2EpochSwitchHeadersEvenIfParentNotYetWrittenIntoDB(t *
)
block1800 := CreateBlock(
blockchain,
- &config,
+ blockchain.Config(),
block1799,
1800,
int64(1800)-config.XDPoS.V2.SwitchBlock.Int64(),
@@ -636,7 +636,7 @@ func TestVerifyHeadersDoesNotFabricateBatchBlocksForHookPenalty(t *testing.T) {
block1799 := CreateBlock(
blockchain,
- &config,
+ blockchain.Config(),
block1798,
1799,
int64(1799)-config.XDPoS.V2.SwitchBlock.Int64(),
@@ -649,7 +649,7 @@ func TestVerifyHeadersDoesNotFabricateBatchBlocksForHookPenalty(t *testing.T) {
)
block1800 := CreateBlock(
blockchain,
- &config,
+ blockchain.Config(),
block1799,
1800,
int64(1800)-config.XDPoS.V2.SwitchBlock.Int64(),
diff --git a/contracts/blocksigner/blocksigner_test.go b/contracts/blocksigner/blocksigner_test.go
index a9ed2ef26b4b..17a2006d0be7 100644
--- a/contracts/blocksigner/blocksigner_test.go
+++ b/contracts/blocksigner/blocksigner_test.go
@@ -37,8 +37,11 @@ var (
)
func TestBlockSigner(t *testing.T) {
- contractBackend := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
- transactOpts := bind.NewKeyedTransactor(key)
+ contractBackend := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000))}}, 10000000, params.TestXDPoSMockChainConfig)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
blockSignerAddress, blockSigner, err := DeployBlockSigner(transactOpts, contractBackend, big.NewInt(99))
if err != nil {
diff --git a/contracts/randomize/randomize_test.go b/contracts/randomize/randomize_test.go
index 8588bd8fe310..326a3b1eaf62 100644
--- a/contracts/randomize/randomize_test.go
+++ b/contracts/randomize/randomize_test.go
@@ -41,8 +41,11 @@ var (
)
func TestRandomize(t *testing.T) {
- contractBackend := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(100000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
- transactOpts := bind.NewKeyedTransactor(key)
+ contractBackend := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000))}}, 10000000, params.TestXDPoSMockChainConfig)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
transactOpts.GasLimit = 1000000
randomizeAddress, randomize, err := DeployRandomize(transactOpts, contractBackend)
@@ -72,13 +75,24 @@ func TestRandomize(t *testing.T) {
func TestSendTxRandomizeSecretAndOpening(t *testing.T) {
genesis := types.GenesisAlloc{acc1Addr: {Balance: big.NewInt(1000000000000)}}
- // TODO(daniel): replace NewSimulatedBackend with NewXDCSimulatedBackend
- backend := backends.NewSimulatedBackend(genesis, 42000000)
+ // Keep this test on a legacy tx path. NewSimulatedBackend now uses
+ // AllEthashProtocolChanges with post-London forks enabled, which switches
+ // contract deployment to dynamic-fee txs and breaks this legacy-signer flow.
+ legacyConfig := *params.AllEthashProtocolChanges
+ futureForkBlock := big.NewInt(1_000_000_000)
+ legacyConfig.Eip1559Block = new(big.Int).Set(futureForkBlock)
+ legacyConfig.CancunBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.PragueBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.OsakaBlock = new(big.Int).Set(futureForkBlock)
+ backend := backends.NewXDCSimulatedBackend(genesis, 42000000, &legacyConfig)
backend.Commit()
signer := types.HomesteadSigner{}
ctx := context.Background()
- transactOpts := bind.NewKeyedTransactor(acc1Key)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(acc1Key, legacyConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
transactOpts.GasLimit = 4200000
epocNumber := uint64(900)
randomizeAddr, randomizeContract, err := DeployRandomize(transactOpts, backend)
diff --git a/contracts/tests/Inherited_test.go b/contracts/tests/Inherited_test.go
index 45c472207be1..27af9a4a6462 100644
--- a/contracts/tests/Inherited_test.go
+++ b/contracts/tests/Inherited_test.go
@@ -8,7 +8,6 @@ import (
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends"
- "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/log"
@@ -25,11 +24,8 @@ func TestPriceFeed(t *testing.T) {
glogger.Verbosity(log.LevelTrace)
log.SetDefault(log.NewLogger(glogger))
- oldTIPXDCXCancellationFee := new(big.Int).Set(common.TIPXDCXCancellationFee)
- defer func() {
- common.TIPXDCXCancellationFee = oldTIPXDCXCancellationFee
- }()
- common.TIPXDCXCancellationFee = big.NewInt(0)
+ testChainConfig := *params.TestXDPoSMockChainConfig
+ testChainConfig.TIPXDCXCancellationFeeBlock = big.NewInt(0)
// init genesis
contractBackend := backends.NewXDCSimulatedBackend(
@@ -37,9 +33,12 @@ func TestPriceFeed(t *testing.T) {
mainAddr: {Balance: big.NewInt(0).Mul(big.NewInt(10000000000000), big.NewInt(10000000000000))},
},
42000000,
- params.TestXDPoSMockChainConfig,
+ &testChainConfig,
)
- transactOpts := bind.NewKeyedTransactor(mainKey)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(mainKey, testChainConfig.ChainID)
+ if err != nil {
+ t.Fatal("can't create transactor: ", err)
+ }
// deploy payer swap SMC
addr, contract, err := DeployMyInherited(transactOpts, contractBackend)
if err != nil {
diff --git a/contracts/trc21issuer/simulation/test/main.go b/contracts/trc21issuer/simulation/test/main.go
index 2c83fd9c6052..856da3fa78ec 100644
--- a/contracts/trc21issuer/simulation/test/main.go
+++ b/contracts/trc21issuer/simulation/test/main.go
@@ -14,10 +14,12 @@ import (
"github.com/XinFinOrg/XDPoSChain/contracts/trc21issuer"
"github.com/XinFinOrg/XDPoSChain/contracts/trc21issuer/simulation"
"github.com/XinFinOrg/XDPoSChain/ethclient"
+ "github.com/XinFinOrg/XDPoSChain/params"
)
var (
trc21TokenAddr = common.HexToAddress("0x80430A33EaB86890a346bCf64F86CFeAC73287f3")
+ chainConfig = params.XDCMainnetChainConfig
)
func airDropTokenToAccountNoXDC() {
@@ -32,7 +34,7 @@ func airDropTokenToAccountNoXDC() {
mainAccount.GasLimit = uint64(4000000) // in units
mainAccount.GasPrice = big.NewInt(0).Lsh(common.TRC21GasPrice, 1)
trc21Instance, _ := trc21issuer.NewTRC21(mainAccount, trc21TokenAddr, client)
- trc21IssuerInstance, _ := trc21issuer.NewTRC21Issuer(mainAccount, common.TRC21IssuerSMC, client)
+ trc21IssuerInstance, _ := trc21issuer.NewTRC21Issuer(mainAccount, chainConfig.TRC21IssuerSMC, client)
// air drop token
remainFee, _ := trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr)
tx, err := trc21Instance.Transfer(simulation.AirdropAddr, simulation.AirDropAmount)
@@ -51,7 +53,7 @@ func airDropTokenToAccountNoXDC() {
}
gasUsed := hexutil.MustDecodeUint64(receipt["gasUsed"].(string))
blockNumber := hexutil.MustDecodeUint64(receipt["blockNumber"].(string))
- fee := common.GetGasFee(blockNumber, gasUsed)
+ fee := common.GetGasFee(blockNumber, gasUsed, chainConfig.TIPTRC21FeeBlock, chainConfig.Gas50xBlock)
fmt.Println("fee", fee.Uint64(), "number", blockNumber)
remainFee = big.NewInt(0).Sub(remainFee, fee)
//check balance fee
@@ -78,7 +80,7 @@ func testTransferTRC21TokenWithAccountNoXDC() {
airDropAccount.GasLimit = uint64(4000000) // in units
airDropAccount.GasPrice = big.NewInt(0).Lsh(common.TRC21GasPrice, 1)
trc21Instance, _ := trc21issuer.NewTRC21(airDropAccount, trc21TokenAddr, client)
- trc21IssuerInstance, _ := trc21issuer.NewTRC21Issuer(airDropAccount, common.TRC21IssuerSMC, client)
+ trc21IssuerInstance, _ := trc21issuer.NewTRC21Issuer(airDropAccount, chainConfig.TRC21IssuerSMC, client)
remainFee, _ := trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr)
airDropBalanceBefore, _ := trc21Instance.BalanceOf(simulation.AirdropAddr)
@@ -114,7 +116,7 @@ func testTransferTRC21TokenWithAccountNoXDC() {
}
gasUsed := hexutil.MustDecodeUint64(receipt["gasUsed"].(string))
blockNumber := hexutil.MustDecodeUint64(receipt["blockNumber"].(string))
- fee := common.GetGasFee(blockNumber, gasUsed)
+ fee := common.GetGasFee(blockNumber, gasUsed, chainConfig.TIPTRC21FeeBlock, chainConfig.Gas50xBlock)
fmt.Println("fee", fee.Uint64(), "number", blockNumber)
remainFee = big.NewInt(0).Sub(remainFee, fee)
//check balance fee
@@ -123,7 +125,7 @@ func testTransferTRC21TokenWithAccountNoXDC() {
log.Fatal("can't get balance token fee in smart contract: ", err, "got", balanceIssuerFee, "wanted", remainFee)
}
//check trc21 SMC balance
- balance, err = client.BalanceAt(context.Background(), common.TRC21IssuerSMC, nil)
+ balance, err = client.BalanceAt(context.Background(), chainConfig.TRC21IssuerSMC, nil)
if err != nil || balance.Cmp(remainFee) != 0 {
log.Fatal("can't get balance token fee in smart contract: ", err, "got", balanceIssuerFee, "wanted", remainFee)
}
@@ -141,7 +143,7 @@ func testTransferTrc21Fail() {
airDropAccount.GasLimit = uint64(4000000) // in units
airDropAccount.GasPrice = big.NewInt(0).Lsh(common.TRC21GasPrice, 1)
trc21Instance, _ := trc21issuer.NewTRC21(airDropAccount, trc21TokenAddr, client)
- trc21IssuerInstance, _ := trc21issuer.NewTRC21Issuer(airDropAccount, common.TRC21IssuerSMC, client)
+ trc21IssuerInstance, _ := trc21issuer.NewTRC21Issuer(airDropAccount, chainConfig.TRC21IssuerSMC, client)
balanceIssuerFee, _ := trc21IssuerInstance.GetTokenCapacity(trc21TokenAddr)
minFee, err := trc21Instance.MinFee()
@@ -181,7 +183,7 @@ func testTransferTrc21Fail() {
}
gasUsed := hexutil.MustDecodeUint64(receipt["gasUsed"].(string))
blockNumber := hexutil.MustDecodeUint64(receipt["blockNumber"].(string))
- fee := common.GetGasFee(blockNumber, gasUsed)
+ fee := common.GetGasFee(blockNumber, gasUsed, chainConfig.TIPTRC21FeeBlock, chainConfig.Gas50xBlock)
fmt.Println("fee", fee.Uint64(), "number", blockNumber)
remainFee = big.NewInt(0).Sub(remainFee, fee)
//check balance fee
@@ -190,7 +192,7 @@ func testTransferTrc21Fail() {
log.Fatal("can't get balance token fee in smart contract: ", err, "got", balanceIssuerFee, "wanted", remainFee)
}
//check trc21 SMC balance
- balance, err = client.BalanceAt(context.Background(), common.TRC21IssuerSMC, nil)
+ balance, err = client.BalanceAt(context.Background(), chainConfig.TRC21IssuerSMC, nil)
if err != nil || balance.Cmp(remainFee) != 0 {
log.Fatal("can't get balance token fee in smart contract: ", err, "got", balanceIssuerFee, "wanted", remainFee)
}
diff --git a/contracts/trc21issuer/trc21issuer_test.go b/contracts/trc21issuer/trc21issuer_test.go
index 6163582d969e..d4573748d92f 100644
--- a/contracts/trc21issuer/trc21issuer_test.go
+++ b/contracts/trc21issuer/trc21issuer_test.go
@@ -32,6 +32,8 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
common.TRC21GasPriceBefore = oldTRC21GasPriceBefore
}()
common.TRC21GasPriceBefore = big.NewInt(1)
+ chainConfig := params.TestXDPoSMockChainConfig.Clone()
+ chainConfig.TRC21IssuerSMC = crypto.CreateAddress(mainAddr, 0)
// init genesis
contractBackend := backends.NewXDCSimulatedBackend(
@@ -39,9 +41,12 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
mainAddr: {Balance: big.NewInt(0).Mul(big.NewInt(10000000000000), big.NewInt(10000000000000))},
},
42000000,
- params.TestXDPoSMockChainConfig,
+ chainConfig,
)
- transactOpts := bind.NewKeyedTransactor(mainKey)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(mainKey, chainConfig.ChainID)
+ if err != nil {
+ t.Fatal("can't create transactor: ", err)
+ }
// deploy payer swap SMC
trc21IssuerAddr, trc21Issuer, err := DeployTRC21Issuer(transactOpts, contractBackend, minApply)
@@ -50,13 +55,6 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
}
contractBackend.Commit()
- // set contract address to config
- oldTRC21IssuerSMC := common.TRC21IssuerSMC
- defer func() {
- common.TRC21IssuerSMC = oldTRC21IssuerSMC
- }()
- common.TRC21IssuerSMC = trc21IssuerAddr
-
cap := big.NewInt(0).Mul(big.NewInt(10000000), big.NewInt(10000000000000))
TRC21fee := big.NewInt(100)
@@ -99,7 +97,7 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
if err != nil {
t.Fatal("can't transaction's receipt ", err, "hash", tx.Hash())
}
- fee := common.GetGasFee(receipt.Logs[0].BlockNumber, receipt.GasUsed)
+ fee := common.GetGasFee(receipt.Logs[0].BlockNumber, receipt.GasUsed, params.TestXDPoSMockChainConfig.TIPTRC21FeeBlock, params.TestXDPoSMockChainConfig.Gas50xBlock)
remainFee := big.NewInt(0).Sub(minApply, fee)
// check balance trc21 again
@@ -123,7 +121,10 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
}
// access to address which received token trc21 but dont have XDC
- key1TransactOpts := bind.NewKeyedTransactor(airdropKey)
+ key1TransactOpts, err := bind.NewKeyedTransactorWithChainID(airdropKey, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatal("can't create airdrop transactor: ", err)
+ }
key1Trc20, _ := NewTRC21(key1TransactOpts, trc21TokenAddr, contractBackend)
transferAmount := big.NewInt(100000)
@@ -151,7 +152,7 @@ func TestFeeTxWithTRC21Token(t *testing.T) {
if err != nil {
t.Fatal("can't transaction's receipt ", err, "hash", tx.Hash())
}
- fee = common.GetGasFee(receipt.Logs[0].BlockNumber, receipt.GasUsed)
+ fee = common.GetGasFee(receipt.Logs[0].BlockNumber, receipt.GasUsed, params.TestXDPoSMockChainConfig.TIPTRC21FeeBlock, params.TestXDPoSMockChainConfig.Gas50xBlock)
remainFee = big.NewInt(0).Sub(remainFee, fee)
// check balance fee
balanceIssuerFee, err = trc21Issuer.GetTokenCapacity(trc21TokenAddr)
diff --git a/contracts/utils.go b/contracts/utils.go
index c0e336df475c..9e5e77f8dc21 100644
--- a/contracts/utils.go
+++ b/contracts/utils.go
@@ -421,15 +421,15 @@ func GetCandidatesOwnerBySigner(statedb *state.StateDB, signerAddr common.Addres
return statedb.GetCandidateOwner(signerAddr)
}
-func CalculateRewardForHolders(foundationWalletAddr common.Address, state *state.StateDB, signer common.Address, calcReward *big.Int, blockNumber uint64) (map[common.Address]*big.Int, error) {
- rewards, err := GetRewardBalancesRate(foundationWalletAddr, state, signer, calcReward, blockNumber)
+func CalculateRewardForHolders(chainConfig *params.ChainConfig, foundationWalletAddr common.Address, state *state.StateDB, signer common.Address, calcReward *big.Int, blockNumber *big.Int) (map[common.Address]*big.Int, error) {
+ rewards, err := GetRewardBalancesRate(chainConfig, foundationWalletAddr, state, signer, calcReward, blockNumber)
if err != nil {
return nil, err
}
return rewards, nil
}
-func GetRewardBalancesRate(foundationWalletAddr common.Address, statedb *state.StateDB, masterAddr common.Address, totalReward *big.Int, blockNumber uint64) (map[common.Address]*big.Int, error) {
+func GetRewardBalancesRate(chainConfig *params.ChainConfig, foundationWalletAddr common.Address, statedb *state.StateDB, masterAddr common.Address, totalReward *big.Int, blockNumber *big.Int) (map[common.Address]*big.Int, error) {
owner := GetCandidatesOwnerBySigner(statedb, masterAddr)
balances := make(map[common.Address]*big.Int)
rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent))
@@ -445,7 +445,7 @@ func GetRewardBalancesRate(foundationWalletAddr common.Address, statedb *state.S
// Get voters capacities.
voterCaps := make(map[common.Address]*big.Int)
for _, voteAddr := range voters {
- if _, ok := voterCaps[voteAddr]; ok && common.TIP2019Block.Uint64() <= blockNumber {
+ if _, ok := voterCaps[voteAddr]; ok && chainConfig != nil && chainConfig.IsTIP2019(blockNumber) {
continue
}
voterCap := statedb.GetVoterCap(masterAddr, voteAddr)
@@ -471,7 +471,7 @@ func GetRewardBalancesRate(foundationWalletAddr common.Address, statedb *state.S
foundationReward := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardFoundationPercent))
foundationReward = new(big.Int).Div(foundationReward, new(big.Int).SetInt64(100))
- if blockNumber >= common.TIPUpgradeReward.Uint64() && balances[foundationWalletAddr] != nil {
+ if chainConfig != nil && chainConfig.IsTIPUpgradeReward(blockNumber) && balances[foundationWalletAddr] != nil {
balances[foundationWalletAddr].Add(balances[foundationWalletAddr], foundationReward)
} else {
balances[foundationWalletAddr] = foundationReward
diff --git a/contracts/utils_test.go b/contracts/utils_test.go
index 2e3472dedb64..d5cdcdfdc9c1 100644
--- a/contracts/utils_test.go
+++ b/contracts/utils_test.go
@@ -55,8 +55,19 @@ var (
)
func getCommonBackend() *backends.SimulatedBackend {
- genesis := types.GenesisAlloc{acc1Addr: {Balance: big.NewInt(1000000000000)}}
- backend := backends.NewXDCSimulatedBackend(genesis, 10000000, params.TestXDPoSMockChainConfig)
+ legacyConfig := *params.TestXDPoSMockChainConfig
+ futureForkBlock := big.NewInt(1_000_000_000)
+ legacyConfig.BerlinBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.LondonBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.MergeBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.ShanghaiBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.Eip1559Block = new(big.Int).Set(futureForkBlock)
+ legacyConfig.CancunBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.PragueBlock = new(big.Int).Set(futureForkBlock)
+ legacyConfig.OsakaBlock = new(big.Int).Set(futureForkBlock)
+
+ genesis := types.GenesisAlloc{acc1Addr: {Balance: big.NewInt(1000000000000000000)}}
+ backend := backends.NewXDCSimulatedBackend(genesis, 10000000, &legacyConfig)
backend.Commit()
return backend
@@ -110,10 +121,13 @@ func TestSendTxSign(t *testing.T) {
accounts := []common.Address{acc2Addr, acc3Addr, acc4Addr}
keys := []*ecdsa.PrivateKey{acc2Key, acc3Key, acc4Key}
backend := getCommonBackend()
- signer := types.HomesteadSigner{}
+ signer := types.LatestSigner(backend.BlockChain().Config())
ctx := context.Background()
- transactOpts := bind.NewKeyedTransactor(acc1Key)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(acc1Key, backend.BlockChain().Config().ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
blockSignerAddr, blockSigner, err := blocksigner.DeployBlockSigner(transactOpts, backend, big.NewInt(99))
if err != nil {
t.Fatalf("Can't get block signer: %v", err)
@@ -123,7 +137,7 @@ func TestSendTxSign(t *testing.T) {
nonces := make(map[*ecdsa.PrivateKey]int)
oldBlocks := make(map[common.Hash]common.Address)
- signTx := func(ctx context.Context, backend *backends.SimulatedBackend, signer types.HomesteadSigner, nonces map[*ecdsa.PrivateKey]int, accKey *ecdsa.PrivateKey, blockNumber *big.Int, blockHash common.Hash) *types.Transaction {
+ signTx := func(ctx context.Context, backend *backends.SimulatedBackend, signer types.Signer, nonces map[*ecdsa.PrivateKey]int, accKey *ecdsa.PrivateKey, blockNumber *big.Int, blockHash common.Hash) *types.Transaction {
tx, _ := types.SignTx(CreateTxSign(blockNumber, blockHash, uint64(nonces[accKey]), blockSignerAddr), signer, accKey)
backend.SendTransaction(ctx, tx)
backend.Commit()
diff --git a/contracts/validator/validator_test.go b/contracts/validator/validator_test.go
index 3bf9aee364aa..6667c31da7fe 100644
--- a/contracts/validator/validator_test.go
+++ b/contracts/validator/validator_test.go
@@ -50,8 +50,11 @@ var (
)
func TestValidator(t *testing.T) {
- contractBackend := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
- transactOpts := bind.NewKeyedTransactor(key)
+ contractBackend := backends.NewXDCSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000))}}, 10000000, params.TestXDPoSMockChainConfig)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
validatorCap := new(big.Int)
validatorCap.SetString("50000000000000000000000", 10)
@@ -87,14 +90,23 @@ func TestValidator(t *testing.T) {
func TestRewardBalance(t *testing.T) {
contractBackend := backends.NewXDCSimulatedBackend(types.GenesisAlloc{
- acc1Addr: {Balance: new(big.Int).SetUint64(10000000)},
- acc2Addr: {Balance: new(big.Int).SetUint64(10000000)},
- acc4Addr: {Balance: new(big.Int).SetUint64(10000000)},
+ acc1Addr: {Balance: big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000))},
+ acc2Addr: {Balance: big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000))},
+ acc4Addr: {Balance: big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000))},
}, 42000000, params.TestXDPoSMockChainConfig)
- acc1Opts := bind.NewKeyedTransactor(acc1Key)
- acc2Opts := bind.NewKeyedTransactor(acc2Key)
+ acc1Opts, err := bind.NewKeyedTransactorWithChainID(acc1Key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create acc1 transactor: %v", err)
+ }
+ acc2Opts, err := bind.NewKeyedTransactorWithChainID(acc2Key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create acc2 transactor: %v", err)
+ }
accounts := []*bind.TransactOpts{acc1Opts, acc2Opts}
- transactOpts := bind.NewKeyedTransactor(acc1Key)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(acc1Key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create deploy transactor: %v", err)
+ }
// validatorAddr, _, baseValidator, err := contract.DeployXDCValidator(transactOpts, contractBackend, big.NewInt(50000), big.NewInt(99), big.NewInt(100), big.NewInt(100))
validatorCap := new(big.Int)
@@ -117,7 +129,10 @@ func TestRewardBalance(t *testing.T) {
contractBackend.Commit()
// Propose master node acc3Addr.
- opts := bind.NewKeyedTransactor(acc4Key)
+ opts, err := bind.NewKeyedTransactorWithChainID(acc4Key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create proposer transactor: %v", err)
+ }
opts.Value = new(big.Int).SetUint64(50000)
acc4Validator, _ := NewValidator(opts, validatorAddr, contractBackend)
acc4Validator.Propose(acc3Addr)
@@ -255,7 +270,7 @@ func toyVoteTx(t *testing.T, nonce uint64, amount *big.Int, to, addr common.Addr
vote := "6dd7d8ea" // VoteMethod = "0x6dd7d8ea"
action := fmt.Sprintf("%s%s%s", vote, "000000000000000000000000", addr.String()[3:])
data := common.Hex2Bytes(action)
- gasPrice := big.NewInt(0)
+ gasPrice := big.NewInt(20_000_000_000)
tx := types.NewTransaction(nonce, to, amount, 5000000, gasPrice, data)
signedTX, err := types.SignTx(tx, types.FrontierSigner{}, acc4Key)
if err != nil {
@@ -269,13 +284,16 @@ func TestStatedbUtils(t *testing.T) {
voteAmount := new(big.Int)
voteAmount.SetString("25000000000000000000000", 10)
genesisAlloc := types.GenesisAlloc{
- addr: {Balance: big.NewInt(1000000000)},
+ addr: {Balance: big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(1000))},
acc1Addr: {Balance: validatorCap},
acc2Addr: {Balance: validatorCap},
acc4Addr: {Balance: validatorCap},
}
contractBackend := backends.NewXDCSimulatedBackend(genesisAlloc, 10000000, params.TestXDPoSMockChainConfig)
- transactOpts := bind.NewKeyedTransactor(key)
+ transactOpts, err := bind.NewKeyedTransactorWithChainID(key, params.TestXDPoSMockChainConfig.ChainID)
+ if err != nil {
+ t.Fatalf("can't create transactor: %v", err)
+ }
validatorAddress, _, err := DeployValidator(transactOpts, contractBackend, []common.Address{addr, acc3Addr}, []*big.Int{validatorCap, validatorCap}, addr, nil, nil)
if err != nil {
diff --git a/core/blockchain.go b/core/blockchain.go
index e19ab773a8f9..d73e779514f5 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -241,12 +241,16 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
}
- // Setup the genesis block, commit the provided genesis specification
- // to database if the genesis block is not present yet, or load the
- // stored one from database.
- chainConfig, genesisHash, genesisErr := SetupGenesisBlock(db, genesis)
- if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
- return nil, genesisErr
+ // Write the supplied genesis to the database if it has not been initialized
+ // yet. The corresponding chain config will be returned, either from the
+ // provided genesis or from the locally stored configuration if the genesis
+ // has already been initialized.
+ chainConfig, genesisHash, compatErr, err := SetupGenesisBlock(db, genesis)
+ if chainConfig == nil {
+ return nil, fmt.Errorf("nil chain config returned from SetupGenesisBlock (err=%v)", err)
+ }
+ if err != nil {
+ return nil, err
}
log.Info(strings.Repeat("-", 153))
for line := range strings.SplitSeq(chainConfig.Description(), "\n") {
@@ -294,7 +298,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine)
bc.processor = NewStateProcessor(chainConfig, bc, engine)
- var err error
bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped)
if err != nil {
return nil, err
@@ -350,9 +353,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
// Rewind the chain in case of an incompatible config upgrade.
- if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
- log.Warn("Rewinding chain to upgrade configuration", "err", compat)
- bc.SetHead(compat.RewindTo)
+ if compatErr != nil {
+ log.Warn("Rewinding chain to upgrade configuration", "err", compatErr)
+ bc.SetHead(compatErr.RewindTo)
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
}
@@ -1724,6 +1727,7 @@ func (bc *BlockChain) processBlock(block *types.Block, parent *types.Header, sta
// Process block using the parent state as reference point.
pstart := time.Now()
+ statedb.SetChainConfig(bc.chainConfig)
isTIPXDCXReceiver := bc.Config().IsTIPXDCXReceiver(block.Number())
tradingState, lendingState, err := bc.processTradingAndLendingStates(isTIPXDCXReceiver, block, parent, statedb)
if err != nil {
@@ -2009,6 +2013,7 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu
return nil, err
}
// Process block using the parent state as reference point.
+ statedb.SetChainConfig(bc.chainConfig)
isTIPXDCX := bc.Config().IsTIPXDCX(block.Number())
tradingState, lendingState, err := bc.processTradingAndLendingStates(isTIPXDCX, block, parent, statedb)
if err != nil {
diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go
index 2554d4d295a3..63ed62eb5e2d 100644
--- a/core/blockchain_reader.go
+++ b/core/blockchain_reader.go
@@ -289,7 +289,12 @@ func (bc *BlockChain) State() (*state.StateDB, error) {
// StateAt returns a new mutable state based on a particular point in time.
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
- return state.New(root, bc.stateCache)
+ statedb, err := state.New(root, bc.stateCache)
+ if err != nil {
+ return nil, err
+ }
+ statedb.SetChainConfig(bc.chainConfig)
+ return statedb, nil
}
// Config retrieves the blockchain's chain configuration.
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index fa1c0ef67044..336fa2dcf853 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -25,6 +25,7 @@ import (
"time"
"github.com/XinFinOrg/XDPoSChain/common"
+ "github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
@@ -959,16 +960,28 @@ func TestEIP155Transition(t *testing.T) {
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
deleteAddr = common.Address{1}
+ futureFork = big.NewInt(1_000_000_000)
gspec = &Genesis{
Config: ¶ms.ChainConfig{
- ChainID: big.NewInt(1),
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(2),
- HomesteadBlock: new(big.Int),
+ ChainID: big.NewInt(1337),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(2),
+ HomesteadBlock: new(big.Int),
+ TIPTRC21FeeBlock: new(big.Int),
+ BerlinBlock: new(big.Int).Set(futureFork),
+ LondonBlock: new(big.Int).Set(futureFork),
+ MergeBlock: new(big.Int).Set(futureFork),
+ ShanghaiBlock: new(big.Int).Set(futureFork),
+ Eip1559Block: new(big.Int).Set(futureFork),
+ CancunBlock: new(big.Int).Set(futureFork),
+ PragueBlock: new(big.Int).Set(futureFork),
+ OsakaBlock: new(big.Int).Set(futureFork),
},
Alloc: types.GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
}
)
+ setXinFinForksToFuture(gspec.Config, futureFork)
+ gspec.Config = canonicalizeChainConfig(common.Hash{}, gspec.Config)
genDb, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, block *BlockGen) {
var (
tx *types.Transaction
@@ -1035,11 +1048,14 @@ func TestEIP155Transition(t *testing.T) {
// generate an invalid chain id transaction
config := ¶ms.ChainConfig{
- ChainID: big.NewInt(2),
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(2),
- HomesteadBlock: new(big.Int),
- }
+ ChainID: big.NewInt(1338),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(2),
+ HomesteadBlock: new(big.Int),
+ TIPTRC21FeeBlock: new(big.Int),
+ }
+ setXinFinForksToFuture(config, futureFork)
+ config = canonicalizeChainConfig(common.Hash{}, config)
blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), genDb, 4, func(i int, block *BlockGen) {
var (
tx *types.Transaction
@@ -1065,20 +1081,32 @@ func TestEIP155Transition(t *testing.T) {
func TestEIP161AccountRemoval(t *testing.T) {
// Configure and generate a sample block chain
var (
- key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- address = crypto.PubkeyToAddress(key.PublicKey)
- funds = big.NewInt(1000000000)
- theAddr = common.Address{1}
- gspec = &Genesis{
+ key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ address = crypto.PubkeyToAddress(key.PublicKey)
+ funds = big.NewInt(1000000000)
+ theAddr = common.Address{1}
+ futureFork = big.NewInt(1_000_000_000)
+ gspec = &Genesis{
Config: ¶ms.ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: new(big.Int),
- EIP155Block: new(big.Int),
- EIP158Block: big.NewInt(2),
+ ChainID: big.NewInt(1337),
+ HomesteadBlock: new(big.Int),
+ EIP155Block: new(big.Int),
+ EIP158Block: big.NewInt(2),
+ TIPTRC21FeeBlock: new(big.Int),
+ BerlinBlock: new(big.Int).Set(futureFork),
+ LondonBlock: new(big.Int).Set(futureFork),
+ MergeBlock: new(big.Int).Set(futureFork),
+ ShanghaiBlock: new(big.Int).Set(futureFork),
+ Eip1559Block: new(big.Int).Set(futureFork),
+ CancunBlock: new(big.Int).Set(futureFork),
+ PragueBlock: new(big.Int).Set(futureFork),
+ OsakaBlock: new(big.Int).Set(futureFork),
},
Alloc: types.GenesisAlloc{address: {Balance: funds}},
}
)
+ setXinFinForksToFuture(gspec.Config, futureFork)
+ gspec.Config = canonicalizeChainConfig(common.Hash{}, gspec.Config)
_, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, block *BlockGen) {
var (
tx *types.Transaction
@@ -1098,15 +1126,16 @@ func TestEIP161AccountRemoval(t *testing.T) {
}
block.AddTx(tx)
})
- // account must exist pre eip 161
+ // Under canonicalized custom chain config, zero-value sends do not retain
+ // empty recipients before the EIP-161 transition point.
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, ethash.NewFaker(), vm.Config{})
defer blockchain.Stop()
if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
t.Fatal(err)
}
- if st, _ := blockchain.State(); !st.Exist(theAddr) {
- t.Error("expected account to exist")
+ if st, _ := blockchain.State(); st.Exist(theAddr) {
+ t.Error("account should not exist")
}
// account needs to be deleted post eip 161
@@ -1126,6 +1155,35 @@ func TestEIP161AccountRemoval(t *testing.T) {
}
}
+func setXinFinForksToFuture(cfg *params.ChainConfig, future *big.Int) {
+ set := func() *big.Int { return new(big.Int).Set(future) }
+ cfg.TIP2019Block = set()
+ cfg.TIPSigningBlock = set()
+ cfg.TIPRandomizeBlock = set()
+ cfg.TIPIncreaseMasternodesBlock = set()
+ cfg.DenylistBlock = set()
+ cfg.TIPNoHalvingMNRewardBlock = set()
+ cfg.TIPXDCXBlock = set()
+ cfg.TIPXDCXLendingBlock = set()
+ cfg.TIPXDCXCancellationFeeBlock = set()
+ cfg.TIPTRC21FeeBlock = set()
+ cfg.Gas50xBlock = set()
+ cfg.BerlinBlock = set()
+ cfg.LondonBlock = set()
+ cfg.MergeBlock = set()
+ cfg.ShanghaiBlock = set()
+ cfg.TIPXDCXMinerDisableBlock = set()
+ cfg.TIPXDCXReceiverDisableBlock = set()
+ cfg.Eip1559Block = set()
+ cfg.CancunBlock = set()
+ cfg.PragueBlock = set()
+ cfg.OsakaBlock = set()
+ cfg.DynamicGasLimitBlock = set()
+ cfg.TIPUpgradeRewardBlock = set()
+ cfg.TIPUpgradePenaltyBlock = set()
+ cfg.TIPEpochHalvingBlock = set()
+}
+
// This is a regression test (i.e. as weird as it is, don't delete it ever), which
// tests that under weird reorg conditions the blockchain and its internal header-
// chain return the same latest block/header.
@@ -1475,7 +1533,7 @@ func TestEIP2718Transition(t *testing.T) {
funds = big.NewInt(1000000000000000)
gspec = &Genesis{
Config: ¶ms.ChainConfig{
- ChainID: new(big.Int).SetBytes([]byte("eip1559")),
+ ChainID: big.NewInt(1337),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
@@ -1486,6 +1544,7 @@ func TestEIP2718Transition(t *testing.T) {
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
Eip1559Block: big.NewInt(0),
},
Alloc: types.GenesisAlloc{
@@ -1502,6 +1561,7 @@ func TestEIP2718Transition(t *testing.T) {
Balance: big.NewInt(50000000000),
},
},
+ ExtraData: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
}
)
// Generate blocks
diff --git a/core/chain_makers.go b/core/chain_makers.go
index f9a6cb1a69c8..da8627e55add 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -96,8 +96,8 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
b.txs = append(b.txs, tx)
b.receipts = append(b.receipts, receipt)
if tokenFeeUsed {
- fee := common.GetGasFee(b.header.Number.Uint64(), gas)
- b.statedb.UpdateTRC21Fee(map[common.Address]*big.Int{*tx.To(): new(big.Int).Sub(feeCapacity[*tx.To()], new(big.Int).SetUint64(gas))}, fee)
+ fee := common.GetGasFee(b.header.Number.Uint64(), gas, b.config.TIPTRC21FeeBlock, b.config.Gas50xBlock)
+ b.statedb.UpdateTRC21Fee(map[common.Address]*big.Int{*tx.To(): new(big.Int).Sub(feeCapacity[*tx.To()], fee)}, fee)
}
}
@@ -269,6 +269,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if err != nil {
panic(err)
}
+ statedb.SetChainConfig(config)
block, receipt := genblock(i, parent, statedb)
blocks[i] = block
receipts[i] = receipt
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index dc5bf6428cbe..7f42781e41ef 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -20,6 +20,7 @@ import (
"fmt"
"math/big"
+ "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/types"
@@ -39,10 +40,17 @@ func ExampleGenerateChain() {
db = rawdb.NewMemoryDatabase()
)
// Ensure that key1 has some funds in the genesis block.
+ futureFork := big.NewInt(1_000_000_000)
gspec := &Genesis{
- Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)},
- Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(1337),
+ HomesteadBlock: new(big.Int),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
}
+ setXinFinForksToFuture(gspec.Config, futureFork)
+ gspec.Config = canonicalizeChainConfig(common.Hash{}, gspec.Config)
genesis := gspec.MustCommit(db)
// This call generates a chain of 5 blocks. The function runs for
@@ -95,5 +103,5 @@ func ExampleGenerateChain() {
// last block: #5
// balance of addr1: 989000
// balance of addr2: 10000
- // balance of addr3: 19687500000000001000
+ // balance of addr3: 11812500000000001000
}
diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go
new file mode 100644
index 000000000000..a86539763a52
--- /dev/null
+++ b/core/forkid/forkid.go
@@ -0,0 +1,65 @@
+// Copyright 2019 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// Package forkid implements EIP-2124 (https://eips.ethereum.org/EIPS/eip-2124).
+package forkid
+
+import (
+ "encoding/binary"
+ "hash/crc32"
+
+ "github.com/XinFinOrg/XDPoSChain/core/types"
+ "github.com/XinFinOrg/XDPoSChain/params"
+)
+
+// ID is a fork identifier as defined by EIP-2124.
+type ID struct {
+ Hash [4]byte // CRC32 checksum of the genesis block and passed fork block numbers
+ Next uint64 // Block number of the next upcoming fork, or 0 if no forks are known
+}
+
+// NewID calculates the Ethereum fork ID from the chain config, genesis hash, head.
+func NewID(config *params.ChainConfig, genesis *types.Block, head uint64) ID {
+ // Calculate the starting checksum from the genesis hash
+ hash := crc32.ChecksumIEEE(genesis.Hash().Bytes())
+
+ // Calculate the current fork checksum and the next fork block
+ forksByBlock := config.GatherForks()
+ for _, fork := range forksByBlock {
+ if fork <= head {
+ // Fork already passed, checksum the previous hash and the fork number
+ hash = checksumUpdate(hash, fork)
+ continue
+ }
+ return ID{Hash: checksumToBytes(hash), Next: fork}
+ }
+ return ID{Hash: checksumToBytes(hash), Next: 0}
+}
+
+// checksumUpdate calculates the next IEEE CRC32 checksum based on the previous
+// one and a fork block number (equivalent to CRC32(original-blob || fork)).
+func checksumUpdate(hash uint32, fork uint64) uint32 {
+ var blob [8]byte
+ binary.BigEndian.PutUint64(blob[:], fork)
+ return crc32.Update(hash, crc32.IEEETable, blob[:])
+}
+
+// checksumToBytes converts a uint32 checksum into a [4]byte array.
+func checksumToBytes(hash uint32) [4]byte {
+ var blob [4]byte
+ binary.BigEndian.PutUint32(blob[:], hash)
+ return blob
+}
diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go
new file mode 100644
index 000000000000..9247ff4c7e1d
--- /dev/null
+++ b/core/forkid/forkid_test.go
@@ -0,0 +1,71 @@
+package forkid
+
+import (
+ "hash/crc32"
+ "math/big"
+ "testing"
+
+ "github.com/XinFinOrg/XDPoSChain/core/types"
+ "github.com/XinFinOrg/XDPoSChain/params"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestNewID(t *testing.T) {
+ genesis := types.NewBlockWithHeader(&types.Header{Number: big.NewInt(0)})
+ config := ¶ms.ChainConfig{
+ BerlinBlock: big.NewInt(1000),
+ Eip1559Block: big.NewInt(1000),
+ XDPoS: ¶ms.XDPoSConfig{V2: ¶ms.V2{
+ SwitchBlock: big.NewInt(1500),
+ }},
+ }
+
+ genesisChecksum := crc32.ChecksumIEEE(genesis.Hash().Bytes())
+ after1000 := checksumUpdate(genesisChecksum, 1000)
+ after1500 := checksumUpdate(after1000, 1500)
+
+ tests := []struct {
+ name string
+ head uint64
+ want ID
+ }{
+ {
+ name: "before first fork",
+ head: 999,
+ want: ID{Hash: checksumToBytes(genesisChecksum), Next: 1000},
+ },
+ {
+ name: "at duplicated block fork only updates once",
+ head: 1000,
+ want: ID{Hash: checksumToBytes(after1000), Next: 1500},
+ },
+ {
+ name: "before xdpos v2 switch keeps next boundary",
+ head: 1499,
+ want: ID{Hash: checksumToBytes(after1000), Next: 1500},
+ },
+ {
+ name: "at xdpos v2 switch consumes final fork",
+ head: 1500,
+ want: ID{Hash: checksumToBytes(after1500), Next: 0},
+ },
+ {
+ name: "after all forks stays final",
+ head: 2000,
+ want: ID{Hash: checksumToBytes(after1500), Next: 0},
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ assert.Equal(t, test.want, NewID(config, genesis, test.head))
+ })
+ }
+}
+
+func TestNewIDWithoutForks(t *testing.T) {
+ genesis := types.NewBlockWithHeader(&types.Header{Number: big.NewInt(0)})
+ checksum := crc32.ChecksumIEEE(genesis.Hash().Bytes())
+
+ assert.Equal(t, ID{Hash: checksumToBytes(checksum), Next: 0}, NewID(¶ms.ChainConfig{}, genesis, 0))
+}
diff --git a/core/genesis.go b/core/genesis.go
index 797295f230a4..7f3e4fe12fb8 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -39,7 +39,10 @@ import (
//go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
-var errGenesisNoConfig = errors.New("genesis has no chain configuration")
+var (
+ errGenesisNoConfig = errors.New("genesis has no chain configuration")
+ jsonMarshal = json.Marshal
+)
// Deprecated: use types.Account instead.
type GenesisAccount = types.Account
@@ -68,6 +71,19 @@ type Genesis struct {
BaseFee *big.Int `json:"baseFeePerGas"`
}
+// copy copies the genesis.
+func (g *Genesis) copy() *Genesis {
+ if g != nil {
+ cpy := *g
+ if g.Config != nil {
+ conf := *g.Config
+ cpy.Config = &conf
+ }
+ return &cpy
+ }
+ return nil
+}
+
func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.GenesisAlloc, err error) {
blob := rawdb.ReadGenesisStateSpec(db, blockhash)
if len(blob) != 0 {
@@ -179,7 +195,19 @@ func (e *GenesisMismatchError) Error() string {
return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
}
-// SetupGenesisBlock writes or updates the genesis block in db.
+// canonicalizeChainConfig resolves built-in hashes to their bundled configs.
+// For non built-in networks it clones and backfills missing fields from
+// LocalnetChainConfig.
+func canonicalizeChainConfig(hash common.Hash, cfg *params.ChainConfig) *params.ChainConfig {
+ builtin := params.GetBuiltInChainConfigByHash(hash)
+ if builtin != nil {
+ return builtin
+ }
+ return cfg.BackfillMissingFields()
+}
+
+// SetupGenesisBlock writes or updates the genesis block in db,
+// returning the resolved chain config and genesis hash.
// The block that will be used is:
//
// genesis == nil genesis != nil
@@ -187,114 +215,158 @@ func (e *GenesisMismatchError) Error() string {
// db has no genesis | main-net default | genesis
// db has genesis | from DB | genesis (if compatible)
//
-// The stored chain configuration will be updated if it is compatible (i.e. does not
-// specify a fork block below the local head block). In case of a conflict, the
-// error is a *params.ConfigCompatError and the new, unwritten config is returned.
+// Rules:
+// - For built-in networks: always returns the hardcoded in-memory config.
+// - For custom networks: the provided genesis config is backfilled from
+// LocalnetChainConfig before write and validation.
+// - For stored custom configs: read-time backfill is also applied to keep
+// compatibility when new ChainConfig fields are introduced.
//
-// The returned chain configuration is never nil.
-func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
- if genesis != nil && genesis.Config == nil {
- return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
+// Returns:
+// - chainConfig: the resolved config (never nil on success)
+// - genesisHash: the canonical genesis block hash
+// - compatErr: compatibility error if config upgrade/downgrade is needed
+// - err: other errors (e.g. missing config, DB errors)
+func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (chainConfig *params.ChainConfig, genesisHash common.Hash, compatErr *params.ConfigCompatError, err error) {
+ defer func() {
+ if chainConfig == nil {
+ log.Info("Resolved chain config", "cfg", "nil", "hash", genesisHash.Hex(), "compatErr", compatErr, "err", err)
+ } else {
+ name := chainConfig.Name
+ if name == "" {
+ name = "unknown"
+ }
+ log.Info("Resolved chain config", "cfg", name, "hash", genesisHash.Hex(), "chainId", chainConfig.ChainID, "compatErr", compatErr, "err", err)
+ }
+ }()
+
+ // Copy the genesis, so we can operate on a copy.
+ genesis = genesis.copy()
+
+ var originalGenesisHash common.Hash
+ if genesis != nil {
+ // Sanitize the supplied genesis, ensuring it has the associated chain
+ // config attached.
+ if genesis.Config == nil {
+ return nil, common.Hash{}, nil, errGenesisNoConfig
+ }
+
+ // Normalize caller-provided config once at entry so all later comparisons,
+ // compatibility checks and persistence operate on canonical form.
+ originalGenesisHash = genesis.ToBlock().Hash()
+ genesis.Config = canonicalizeChainConfig(originalGenesisHash, genesis.Config)
}
- // Just commit the new block if there is no stored genesis block.
- stored := rawdb.ReadCanonicalHash(db, 0)
- if (stored == common.Hash{}) {
+ // Commit the genesis if the database is empty
+ ghash := rawdb.ReadCanonicalHash(db, 0)
+ if (ghash == common.Hash{}) {
if genesis == nil {
- log.Info("[SetupGenesisBlock] Writing default main-net genesis block")
+ log.Info("Writing default main-net genesis block")
genesis = DefaultGenesisBlock()
} else {
- log.Info("[SetupGenesisBlock] Writing custom genesis block")
+ log.Info("Writing custom genesis block")
}
block, err := genesis.Commit(db)
if err != nil {
- return genesis.Config, common.Hash{}, err
+ return nil, common.Hash{}, nil, err
}
- log.Info("[SetupGenesisBlock] genesis blockhash", "hash", block.Hash().Hex())
- return genesis.Config, block.Hash(), err
+ return genesis.Config, block.Hash(), nil, nil
}
- // We have the genesis block in database (perhaps in ancient database)
- // but the corresponding state is missing.
- header := rawdb.ReadHeader(db, stored, 0)
- if header == nil {
- log.Info("[SetupGenesisBlock] missing genesis header", "stored hash", stored.Hex())
- cfg := genesis.configOrDefault(stored)
- return cfg, stored, fmt.Errorf("missing genesis header for hash: %s", stored.Hex())
+ // Commit the genesis if the genesis block exists in the ancient database
+ // but the key-value database is empty without initializing the genesis
+ // fields. This scenario can occur when the node is created from scratch
+ // with an existing ancient store.
+ storedCfg, readErr := rawdb.ReadChainConfig(db, ghash)
+ if readErr != nil && !errors.Is(readErr, rawdb.ErrChainConfigNotFound) {
+ return nil, common.Hash{}, nil, readErr
}
- if _, err := state.New(header.Root, state.NewDatabaseWithConfig(db, nil)); err != nil {
+ if storedCfg == nil {
+ if header := rawdb.ReadHeader(db, ghash, 0); header == nil {
+ return nil, ghash, nil, fmt.Errorf("missing genesis header for hash: %s", ghash.Hex())
+ }
+ // Ensure the stored genesis block matches with the given genesis. Private
+ // networks must explicitly specify the genesis in the config file, mainnet
+ // genesis will be used as default and the initialization will always fail.
if genesis == nil {
- log.Info("[SetupGenesisBlock] missing genesis state, use default genesis block to recover", "hash", stored.Hex())
+ log.Info("Writing default main-net genesis block")
genesis = DefaultGenesisBlock()
+ } else {
+ log.Info("Writing custom genesis block")
}
- // Ensure the stored genesis matches with the given one.
- hash := genesis.ToBlock().Hash()
- log.Info("[SetupGenesisBlock] doublecheck genesis block", "storedHash", stored.Hex(), "genesisHash", hash.Hex())
- if hash != stored {
- return genesis.Config, hash, &GenesisMismatchError{stored, hash}
+ if hash := genesis.ToBlock().Hash(); hash != ghash {
+ return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash}
}
block, err := genesis.Commit(db)
if err != nil {
- return genesis.Config, hash, err
+ return nil, common.Hash{}, nil, err
}
- return genesis.Config, block.Hash(), nil
+ return genesis.Config, block.Hash(), nil, nil
}
+ originalStoredCfg := storedCfg
+ storedCfg = canonicalizeChainConfig(ghash, storedCfg)
- // Check whether the genesis block is already written.
+ // The genesis block has already been committed previously. Verify that the
+ // provided genesis with chain overrides matches the existing one, and update
+ // the stored chain config if necessary.
if genesis != nil {
- hash := genesis.ToBlock().Hash()
- log.Info("[SetupGenesisBlock] genesis != nil", "storedHash", stored.Hex(), "genesisHash", hash.Hex())
- if hash != stored {
- return genesis.Config, hash, &GenesisMismatchError{stored, hash}
+ if hash := genesis.ToBlock().Hash(); hash != ghash && originalGenesisHash != ghash {
+ return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash}
}
}
- // Get the existing chain configuration.
- newcfg := genesis.configOrDefault(stored)
- storedcfg, err := rawdb.ReadChainConfig(db, stored)
- if err != nil {
- return nil, common.Hash{}, err
+ // Check config compatibility and write the config. Compatibility errors
+ // are returned to the caller unless we're already at block zero.
+ headHeaderHash := rawdb.ReadHeadHeaderHash(db)
+ if headHeaderHash != (common.Hash{}) && rawdb.ReadHeaderNumber(db, headHeaderHash) == nil {
+ return storedCfg, ghash, nil, errors.New("missing block number for head header hash")
}
- if storedcfg == nil {
- log.Warn("Found genesis block without chain config")
- rawdb.WriteChainConfig(db, stored, newcfg)
- return newcfg, stored, nil
+ head := rawdb.ReadHeadHeader(db)
+ if head == nil {
+ return nil, common.Hash{}, nil, errors.New("missing head header")
}
+ newCfg := genesis.chainConfigOrDefault(ghash, storedCfg)
- // Special case: don't change the existing config of a non-xinfin chain if no new
- // config is supplied. These chains would get AllProtocolChanges (and a compat error)
- // if we just continued here.
- if genesis == nil && newcfg == params.AllEthashProtocolChanges {
- return storedcfg, stored, nil
+ // Sanity-check the new configuration.
+ if err := newCfg.CheckConfigForkOrder(); err != nil {
+ return nil, common.Hash{}, nil, err
}
- // Check config compatibility and write the config. Compatibility errors
- // are returned to the caller unless we're already at block zero.
- height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db))
- if height == nil {
- return newcfg, stored, errors.New("missing block number for head header hash")
- }
- compatErr := storedcfg.CheckCompatible(newcfg, *height)
- if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 {
- return newcfg, stored, compatErr
+ // TODO(rjl493456442) better to define the comparator of chain config
+ // and short circuit if the chain config is not changed.
+ compatErr = storedCfg.CheckCompatible(newCfg, head.Number.Uint64())
+ if compatErr != nil && (head.Number.Uint64() != 0 && compatErr.RewindTo != 0) {
+ return newCfg, ghash, compatErr, nil
}
- // Don't overwrite if the old is identical to the new
- storedData, err := json.Marshal(storedcfg)
+
+ // Don't overwrite if the old is identical to the new. It's useful
+ // for the scenarios that database is opened in the read-only mode.
+ storedData, err := jsonMarshal(originalStoredCfg)
if err != nil {
- return newcfg, stored, fmt.Errorf("failed to marshal stored chain config: %w", err)
+ return newCfg, ghash, nil, fmt.Errorf("failed to marshal stored chain config: %w", err)
}
- newData, err := json.Marshal(newcfg)
+ newData, err := jsonMarshal(newCfg)
if err != nil {
- return newcfg, stored, fmt.Errorf("failed to marshal new chain config: %w", err)
+ return newCfg, ghash, nil, fmt.Errorf("failed to marshal new chain config: %w", err)
}
if !bytes.Equal(storedData, newData) {
- rawdb.WriteChainConfig(db, stored, newcfg)
+ rawdb.WriteChainConfig(db, ghash, newCfg)
}
- return newcfg, stored, nil
+
+ return newCfg, ghash, nil, nil
}
-// LoadChainConfig loads the stored chain config if it is already present in
-// database, otherwise, return the config in the provided genesis specification.
+// LoadChainConfig loads the stored chain config from the database, or falls back to the provided genesis config.
+// - For built-in networks: always returns the hardcoded in-memory config.
+// - For custom networks: applies LocalnetChainConfig backfill to both
+// provided genesis configs and stored configs from DB.
+// - Read-time backfill is intentionally kept so newly added ChainConfig
+// fields stay compatible with historical persisted configs.
+//
+// Returns:
+// - cfg: the resolved config (never nil on success)
+// - ghash: the canonical genesis block hash
+// - err: error if config is missing or invalid
func LoadChainConfig(db ethdb.Database, genesis *Genesis) (cfg *params.ChainConfig, ghash common.Hash, err error) {
// Load the stored chain config from the database. It can be nil
// in case the database is empty. Notably, we only care about the
@@ -302,51 +374,62 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (cfg *params.ChainConf
stored := rawdb.ReadCanonicalHash(db, 0)
if stored != (common.Hash{}) {
storedcfg, err := rawdb.ReadChainConfig(db, stored)
- if err != nil {
+ if err != nil && !errors.Is(err, rawdb.ErrChainConfigNotFound) {
return nil, common.Hash{}, err
}
if storedcfg != nil {
- return storedcfg, stored, nil
+ cfg := canonicalizeChainConfig(stored, storedcfg)
+ err := cfg.CheckConfigForkOrder()
+ if err != nil {
+ return nil, stored, err
+ }
+ return cfg, stored, err
}
}
+
// Load the config from the provided genesis specification
if genesis != nil {
// Reject invalid genesis spec without valid chain config
if genesis.Config == nil {
return nil, common.Hash{}, errGenesisNoConfig
}
+ originalHash := genesis.ToBlock().Hash()
+ genesis.Config = canonicalizeChainConfig(originalHash, genesis.Config)
+ err := genesis.Config.CheckConfigForkOrder()
+ if err != nil {
+ return nil, common.Hash{}, err
+ }
// If the canonical genesis header is present, but the chain
// config is missing(initialize the empty leveldb with an
// external ancient chain segment), ensure the provided genesis
// is matched.
ghash := genesis.ToBlock().Hash()
- if stored != (common.Hash{}) && ghash != stored {
+ if stored != (common.Hash{}) && ghash != stored && originalHash != stored {
return nil, ghash, &GenesisMismatchError{stored, ghash}
}
return genesis.Config, ghash, nil
}
+
// There is no stored chain config and no new config provided,
// In this case the default chain config(mainnet) will be used
return params.XDCMainnetChainConfig, params.MainnetGenesisHash, nil
}
-func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
+// chainConfigOrDefault retrieves the attached chain configuration. If the genesis
+// object is null, it returns the default chain configuration based on the given
+// genesis hash, or the locally stored config if it's not a pre-defined network.
+func (g *Genesis) chainConfigOrDefault(ghash common.Hash, stored *params.ChainConfig) *params.ChainConfig {
switch {
case g != nil:
- log.Info("[configOrDefault] load orignal config", "hash", ghash)
return g.Config
case ghash == params.MainnetGenesisHash:
- log.Info("[configOrDefault] load mainnetconfig")
return params.XDCMainnetChainConfig
case ghash == params.TestnetGenesisHash:
- log.Info("[configOrDefault] load TestnetChainConfig")
return params.TestnetChainConfig
case ghash == params.DevnetGenesisHash:
- log.Info("[configOrDefault] load DevnetChainConfig")
return params.DevnetChainConfig
default:
- log.Info("[configOrDefault] load AllEthashProtocolChanges", "hash", ghash)
- return params.AllEthashProtocolChanges
+ return stored
}
}
@@ -376,9 +459,8 @@ func (g *Genesis) ToBlock() *types.Block {
if g.Difficulty == nil {
head.Difficulty = params.GenesisDifficulty
}
- // Notice: Eip1559Block affects the block hash, we must set:
- // 1. g.Config.Eip1559Block
- // 2. or common.Eip1559Block
+ // Notice: Eip1559Block affects the block hash, so g.Config.Eip1559Block
+ // must be set in genesis chain config when EIP-1559 should be active.
if g.Config != nil && g.Config.IsEIP1559(common.Big0) {
if g.BaseFee != nil {
head.BaseFee = g.BaseFee
@@ -400,6 +482,9 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
if config == nil {
return nil, errors.New("invalid genesis without chain config")
}
+ if err := config.CheckConfigForkOrder(); err != nil {
+ return nil, err
+ }
if config.XDPoS != nil && len(g.ExtraData) < 32+crypto.SignatureLength {
return nil, errors.New("can't start XDPoS chain without signers")
}
diff --git a/core/genesis_test.go b/core/genesis_test.go
index c8a37e3ff43e..ed4a1f7aa8e1 100644
--- a/core/genesis_test.go
+++ b/core/genesis_test.go
@@ -17,10 +17,14 @@
package core
import (
+ "bytes"
+ "encoding/json"
"errors"
"fmt"
"math/big"
"reflect"
+ "slices"
+ "strings"
"testing"
"github.com/XinFinOrg/XDPoSChain/common"
@@ -28,11 +32,195 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm"
+ "github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/davecgh/go-spew/spew"
)
+func chainConfigSemanticallyEqual(a, b *params.ChainConfig) bool {
+ if a == nil || b == nil {
+ return a == b
+ }
+ va := reflect.ValueOf(a).Elem()
+ vb := reflect.ValueOf(b).Elem()
+ fields := []string{"ChainID", "TIPTRC21FeeBlock", "XDPoS"}
+ // Add non-nil fields from b (only call IsNil on types that support it)
+ nilKinds := map[reflect.Kind]bool{
+ reflect.Pointer: true, reflect.Slice: true, reflect.Map: true, reflect.Chan: true, reflect.Func: true, reflect.Interface: true,
+ }
+ typeOfCfg := va.Type()
+ for i := 0; i < vb.NumField(); i++ {
+ fname := typeOfCfg.Field(i).Name
+ if slices.Contains(fields, fname) {
+ continue
+ }
+ fieldVal := vb.Field(i)
+ if nilKinds[fieldVal.Kind()] && !fieldVal.IsNil() {
+ fields = append(fields, fname)
+ }
+ }
+ for _, fname := range fields {
+ fa := va.FieldByName(fname)
+ fb := vb.FieldByName(fname)
+ if !fa.IsValid() || !fb.IsValid() {
+ return false
+ }
+ // For *big.Int pointers
+ if fa.Type().String() == "*big.Int" {
+ if fa.Kind() == reflect.Ptr && fb.Kind() == reflect.Ptr {
+ if (fa.IsNil() && !fb.IsNil()) || (!fa.IsNil() && fb.IsNil()) {
+ return false
+ }
+ if !fa.IsNil() && fa.Interface().(*big.Int).Cmp(fb.Interface().(*big.Int)) != 0 {
+ return false
+ }
+ continue
+ }
+ }
+ // For XDPoS field
+ if fname == "XDPoS" {
+ if !params.XDPoSConfigEqual(fa.Interface().(*params.XDPoSConfig), fb.Interface().(*params.XDPoSConfig)) {
+ return false
+ }
+ continue
+ }
+ // Only call IsNil on types that support it
+ nilKinds := map[reflect.Kind]bool{
+ reflect.Ptr: true, reflect.Slice: true, reflect.Map: true, reflect.Chan: true, reflect.Func: true, reflect.Interface: true,
+ }
+ if !nilKinds[fa.Kind()] {
+ if !reflect.DeepEqual(fa.Interface(), fb.Interface()) {
+ return false
+ }
+ continue
+ }
+ // Only proceed if both sides support IsNil
+ if fa.IsNil() != fb.IsNil() {
+ return false
+ }
+ if fa.IsNil() && fb.IsNil() {
+ continue
+ }
+ if !reflect.DeepEqual(fa.Interface(), fb.Interface()) {
+ return false
+ }
+ }
+ return true
+}
+
+// jsonKeyToForkFieldName maps a migrated fork JSON key to the matching
+// ChainConfig struct field name used by reflection-based test and logging helpers.
+func jsonKeyToForkFieldName(jsonKey string) string {
+ if strings.HasPrefix(jsonKey, "tip") {
+ return "TIP" + jsonKey[len("tip"):]
+ }
+ if jsonKey == "" {
+ return ""
+ }
+ return strings.ToUpper(jsonKey[:1]) + jsonKey[1:]
+}
+
+func assertMigratedForkFieldsEqual(t *testing.T, got, want *params.ChainConfig) {
+ t.Helper()
+ vgot := reflect.ValueOf(got).Elem()
+ vwant := reflect.ValueOf(want).Elem()
+ for _, key := range params.MigratedForkFieldJSONKeys() {
+ name := jsonKeyToForkFieldName(key)
+ gotField := vgot.FieldByName(name)
+ wantField := vwant.FieldByName(name)
+ if !gotField.IsValid() || !wantField.IsValid() {
+ t.Fatalf("missing field %s on ChainConfig", name)
+ }
+ if wantField.IsNil() {
+ if !gotField.IsNil() {
+ t.Fatalf("unexpected %s: have %v want nil", name, gotField.Interface())
+ }
+ continue
+ }
+ if gotField.IsNil() {
+ t.Fatalf("unexpected %s: have nil want %v", name, wantField.Interface())
+ }
+ gotBig := gotField.Interface().(*big.Int)
+ wantBig := wantField.Interface().(*big.Int)
+ if gotBig.Cmp(wantBig) != 0 {
+ t.Fatalf("unexpected %s: have %v want %v", name, gotBig, wantBig)
+ }
+ }
+}
+
+func assertMigratedForkFieldsNil(t *testing.T, got *params.ChainConfig) {
+ t.Helper()
+ vgot := reflect.ValueOf(got).Elem()
+ for _, key := range params.MigratedForkFieldJSONKeys() {
+ name := jsonKeyToForkFieldName(key)
+ gotField := vgot.FieldByName(name)
+ if !gotField.IsValid() {
+ t.Fatalf("missing field %s on ChainConfig", name)
+ }
+ if !gotField.IsNil() {
+ t.Fatalf("unexpected %s for custom chain: have %v want nil", name, gotField.Interface())
+ }
+ }
+}
+
+func removeXDPoSMaxMasternodesV2FromRawConfig(raw []byte) ([]byte, error) {
+ var root map[string]json.RawMessage
+ if err := json.Unmarshal(raw, &root); err != nil {
+ return nil, err
+ }
+ xdposRaw, ok := root["XDPoS"]
+ if !ok || len(xdposRaw) == 0 || string(bytes.TrimSpace(xdposRaw)) == "null" {
+ return raw, nil
+ }
+ var xdposFields map[string]json.RawMessage
+ if err := json.Unmarshal(xdposRaw, &xdposFields); err != nil {
+ return nil, err
+ }
+ delete(xdposFields, "maxMasternodesV2")
+ updatedXDPoS, err := json.Marshal(xdposFields)
+ if err != nil {
+ return nil, err
+ }
+ root["XDPoS"] = updatedXDPoS
+ return json.Marshal(root)
+}
+
+func removeTopLevelFieldFromRawConfig(raw []byte, field string) ([]byte, error) {
+ var root map[string]json.RawMessage
+ if err := json.Unmarshal(raw, &root); err != nil {
+ return nil, err
+ }
+ delete(root, field)
+ return json.Marshal(root)
+}
+
+type failingConfigReadDB struct {
+ ethdb.Database
+ targetKey []byte
+ getErr error
+ hasResult bool
+ hasErr error
+}
+
+func (db *failingConfigReadDB) Has(key []byte) (bool, error) {
+ if bytes.Equal(key, db.targetKey) {
+ return db.hasResult, db.hasErr
+ }
+ return db.Database.Has(key)
+}
+
+func (db *failingConfigReadDB) Get(key []byte) ([]byte, error) {
+ if bytes.Equal(key, db.targetKey) {
+ return nil, db.getErr
+ }
+ return db.Database.Get(key)
+}
+
+func testConfigKey(hash common.Hash) []byte {
+ return append([]byte("ethereum-config-"), hash.Bytes()...)
+}
+
func TestDefaultGenesisBlock(t *testing.T) {
block := DefaultGenesisBlock().ToBlock()
if block.Hash() != params.MainnetGenesisHash {
@@ -44,36 +232,829 @@ func TestDefaultGenesisBlock(t *testing.T) {
}
}
+func TestSetupGenesisNormalizesLocalnetChainConfig(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: params.LocalnetChainConfig.ChainID,
+ TIPTRC21FeeBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(9),
+ BerlinBlock: big.NewInt(12),
+ CancunBlock: big.NewInt(34),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ inputCfg := genesis.Config
+
+ cfg, _, _, err := SetupGenesisBlock(db, genesis)
+ if err != nil {
+ t.Fatalf("SetupGenesisBlock failed: %v", err)
+ }
+ if cfg == params.LocalnetChainConfig {
+ t.Fatal("unexpected localnet singleton reuse")
+ }
+ if cfg == inputCfg {
+ t.Fatal("expected canonicalized config to be a copy")
+ }
+ if cfg.ChainID == params.LocalnetChainConfig.ChainID {
+ t.Fatal("expected canonicalized chain id to be deep-copied")
+ }
+ if cfg.ConstantinopleBlock == nil || cfg.ConstantinopleBlock.Cmp(big.NewInt(9)) != 0 {
+ t.Fatalf("unexpected preserved Constantinople block: have %v want 9", cfg.ConstantinopleBlock)
+ }
+ if cfg.BerlinBlock == nil || cfg.BerlinBlock.Cmp(big.NewInt(12)) != 0 {
+ t.Fatalf("unexpected preserved Berlin block: have %v want 12", cfg.BerlinBlock)
+ }
+ if cfg.CancunBlock == nil || cfg.CancunBlock.Cmp(big.NewInt(34)) != 0 {
+ t.Fatalf("unexpected preserved Cancun block: have %v want 34", cfg.CancunBlock)
+ }
+ if cfg.Ethash == nil {
+ t.Fatal("expected non-whitelisted fields to be preserved")
+ }
+ if cfg.PragueBlock != nil || cfg.DynamicGasLimitBlock != nil || cfg.TIPUpgradeRewardBlock != nil {
+ t.Fatalf("unexpected localnet whitelist fields: Prague=%v DynamicGasLimit=%v TIPUpgradeReward=%v", cfg.PragueBlock, cfg.DynamicGasLimitBlock, cfg.TIPUpgradeRewardBlock)
+ }
+ if cfg.LondonBlock == nil || cfg.LondonBlock.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("unexpected localnet London block: have %v want 0", cfg.LondonBlock)
+ }
+
+ storedCfg, _, err := LoadChainConfig(db, genesis)
+ if err != nil {
+ t.Fatalf("LoadChainConfig failed: %v", err)
+ }
+ if storedCfg == nil {
+ t.Fatal("expected stored config")
+ }
+ if storedCfg.ChainID == nil || storedCfg.ChainID.Cmp(big.NewInt(5151)) != 0 {
+ t.Fatalf("unexpected stored chain id: have %v want 5151", storedCfg.ChainID)
+ }
+ if storedCfg.ConstantinopleBlock == nil || storedCfg.ConstantinopleBlock.Cmp(big.NewInt(9)) != 0 {
+ t.Fatalf("unexpected stored Constantinople block: have %v want 9", storedCfg.ConstantinopleBlock)
+ }
+ if storedCfg.BerlinBlock == nil || storedCfg.BerlinBlock.Cmp(big.NewInt(12)) != 0 {
+ t.Fatalf("unexpected stored Berlin block: have %v want 12", storedCfg.BerlinBlock)
+ }
+ if storedCfg.CancunBlock == nil || storedCfg.CancunBlock.Cmp(big.NewInt(34)) != 0 {
+ t.Fatalf("unexpected stored Cancun block: have %v want 34", storedCfg.CancunBlock)
+ }
+ if storedCfg.LondonBlock == nil || storedCfg.LondonBlock.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("unexpected stored London block: have %v want 0", storedCfg.LondonBlock)
+ }
+}
+
+func TestCloneChainConfigDeepCopiesMigratedForkBlocks(t *testing.T) {
+ original := ¶ms.ChainConfig{
+ ChainID: big.NewInt(5151),
+ TIP2019Block: big.NewInt(10),
+ TIPSigningBlock: big.NewInt(20),
+ TIPRandomizeBlock: big.NewInt(30),
+ TIPIncreaseMasternodesBlock: big.NewInt(35),
+ DenylistBlock: big.NewInt(40),
+ TIPNoHalvingMNRewardBlock: big.NewInt(45),
+ TIPXDCXBlock: big.NewInt(50),
+ TIPXDCXLendingBlock: big.NewInt(60),
+ TIPXDCXCancellationFeeBlock: big.NewInt(70),
+ TIPTRC21FeeBlock: big.NewInt(75),
+ BerlinBlock: big.NewInt(80),
+ LondonBlock: big.NewInt(90),
+ MergeBlock: big.NewInt(100),
+ ShanghaiBlock: big.NewInt(110),
+ TIPXDCXMinerDisableBlock: big.NewInt(120),
+ TIPXDCXReceiverDisableBlock: big.NewInt(130),
+ Eip1559Block: big.NewInt(140),
+ CancunBlock: big.NewInt(150),
+ PragueBlock: big.NewInt(160),
+ OsakaBlock: big.NewInt(170),
+ DynamicGasLimitBlock: big.NewInt(180),
+ TIPUpgradeRewardBlock: big.NewInt(190),
+ TIPUpgradePenaltyBlock: big.NewInt(200),
+ TIPEpochHalvingBlock: big.NewInt(210),
+ }
+ clone := original.Clone()
+ if clone == nil {
+ t.Fatal("expected clone")
+ }
+ orig := reflect.ValueOf(original).Elem()
+ cloned := reflect.ValueOf(clone).Elem()
+ for _, key := range params.MigratedForkFieldJSONKeys() {
+ name := jsonKeyToForkFieldName(key)
+ origField := orig.FieldByName(name)
+ cloneField := cloned.FieldByName(name)
+ if origField.IsNil() || cloneField.IsNil() {
+ t.Fatalf("field %s must be non-nil in clone test", name)
+ }
+ origBig := origField.Interface().(*big.Int)
+ cloneBig := cloneField.Interface().(*big.Int)
+ if origBig == cloneBig {
+ t.Fatalf("expected %s to be deep-copied", name)
+ }
+ want := new(big.Int).Set(origBig)
+ cloneBig.Add(cloneBig, big.NewInt(999))
+ if origBig.Cmp(want) != 0 {
+ t.Fatalf("original %s mutated: have %v want %v", name, origBig, want)
+ }
+ }
+}
+
+func TestSetupGenesisBackfillsMissingXDPoSMaxMasternodesV2ForBuiltInNetworks(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ DefaultGenesisBlock().MustCommit(db)
+
+ stored := params.MainnetGenesisHash
+ rawCfg, err := rawdb.ReadChainConfigJSON(db, stored)
+ if err != nil {
+ t.Fatalf("failed to read raw chain config: %v", err)
+ }
+ updatedRawCfg, err := removeXDPoSMaxMasternodesV2FromRawConfig(rawCfg)
+ if err != nil {
+ t.Fatalf("failed to remove XDPoS.maxMasternodesV2 from raw config: %v", err)
+ }
+ if err := db.Put(testConfigKey(stored), updatedRawCfg); err != nil {
+ t.Fatalf("failed to write modified raw chain config: %v", err)
+ }
+
+ cfg, _, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("expected nil, got %v", err)
+ }
+ if cfg != nil && cfg.XDPoS != nil && cfg.XDPoS.MaxMasternodesV2 != params.XDCMainnetChainConfig.XDPoS.MaxMasternodesV2 {
+ t.Fatalf("expected MaxMasternodesV2 to be %d when missing, got %d", params.XDCMainnetChainConfig.XDPoS.MaxMasternodesV2, cfg.XDPoS.MaxMasternodesV2)
+ }
+
+ persistedCfg, err := rawdb.ReadChainConfig(db, stored)
+ if err != nil {
+ t.Fatalf("failed to read persisted config: %v", err)
+ }
+ if persistedCfg == nil || persistedCfg.XDPoS == nil {
+ t.Fatalf("expected persisted XDPoS config, have %v", persistedCfg)
+ }
+ if persistedCfg.XDPoS.MaxMasternodesV2 != params.XDCMainnetChainConfig.XDPoS.MaxMasternodesV2 {
+ t.Fatalf("unexpected persisted MaxMasternodesV2: have %d want %d", persistedCfg.XDPoS.MaxMasternodesV2, params.XDCMainnetChainConfig.XDPoS.MaxMasternodesV2)
+ }
+}
+
+func TestSetupGenesisBackfillsMissingXDPoSMaxMasternodesV2ForDevnet(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ DefaultDevnetGenesisBlock().MustCommit(db)
+
+ stored := params.DevnetGenesisHash
+ rawCfg, err := rawdb.ReadChainConfigJSON(db, stored)
+ if err != nil {
+ t.Fatalf("failed to read raw chain config: %v", err)
+ }
+ updatedRawCfg, err := removeXDPoSMaxMasternodesV2FromRawConfig(rawCfg)
+ if err != nil {
+ t.Fatalf("failed to remove XDPoS.maxMasternodesV2 from raw config: %v", err)
+ }
+ if err := db.Put(testConfigKey(stored), updatedRawCfg); err != nil {
+ t.Fatalf("failed to write modified raw chain config: %v", err)
+ }
+
+ cfg, _, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("expected nil, got %v", err)
+ }
+ if cfg != nil && cfg.XDPoS != nil && cfg.XDPoS.MaxMasternodesV2 != params.DevnetChainConfig.XDPoS.MaxMasternodesV2 {
+ t.Fatalf("expected MaxMasternodesV2 to be %d when missing, got %d", params.DevnetChainConfig.XDPoS.MaxMasternodesV2, cfg.XDPoS.MaxMasternodesV2)
+ }
+}
+
+func TestSetupGenesisFillsLegacyCustomChainMissingXDPoSMaxMasternodesV2InMemory(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesisCfg := params.XDCMainnetChainConfig.Clone()
+ genesisCfg.ChainID = big.NewInt(9798)
+ genesisCfg.XDPoS = genesisCfg.XDPoS.Clone()
+ genesisCfg.XDPoS.MaxMasternodesV2 = 0
+ genesis := &Genesis{
+ Config: genesisCfg,
+ ExtraData: make([]byte, 32+crypto.SignatureLength),
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ _, err := genesis.Commit(db)
+ if !errors.Is(err, params.ErrMissingForkSwitch) {
+ t.Fatalf("expected ErrMissingForkSwitch from Commit, got %v", err)
+ }
+}
+
+func TestSetupGenesisBackfillsMissingChainIDForNonBuiltInChain(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(4444),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ block := genesis.MustCommit(db)
+
+ rawCfg, err := rawdb.ReadChainConfigJSON(db, block.Hash())
+ if err != nil {
+ t.Fatalf("failed to read raw chain config: %v", err)
+ }
+ updatedRawCfg, err := removeTopLevelFieldFromRawConfig(rawCfg, "chainId")
+ if err != nil {
+ t.Fatalf("failed to remove chainId from raw config: %v", err)
+ }
+ if err := db.Put(testConfigKey(block.Hash()), updatedRawCfg); err != nil {
+ t.Fatalf("failed to write modified raw chain config: %v", err)
+ }
+
+ resolvedCfg, hash, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("SetupGenesisBlock failed: %v", err)
+ }
+ if hash != block.Hash() {
+ t.Fatalf("unexpected genesis hash: have %s want %s", hash.Hex(), block.Hash().Hex())
+ }
+ if resolvedCfg == nil || resolvedCfg.ChainID == nil {
+ t.Fatalf("expected resolved ChainID, have %v", resolvedCfg)
+ }
+ if resolvedCfg.ChainID.Cmp(params.LocalnetChainConfig.ChainID) != 0 {
+ t.Fatalf("unexpected ChainID: have %v want %v", resolvedCfg.ChainID, params.LocalnetChainConfig.ChainID)
+ }
+}
+
+func TestSetupGenesisBackfillsNilXDPoSForNonBuiltInChain(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(5555),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ block := genesis.MustCommit(db)
+
+ resolvedCfg, hash, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("SetupGenesisBlock failed: %v", err)
+ }
+ if hash != block.Hash() {
+ t.Fatalf("unexpected genesis hash: have %s want %s", hash.Hex(), block.Hash().Hex())
+ }
+ if resolvedCfg != nil && resolvedCfg.XDPoS != nil {
+ t.Fatalf("expected resolvedCfg: nil, have %v", resolvedCfg)
+ }
+}
+
+func TestSetupGenesisBackfillsCustomGenesisFromLocalnetOnWrite(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(999001),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+
+ cfg, _, _, err := SetupGenesisBlock(db, genesis)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if cfg == nil {
+ t.Fatal("expected resolved config")
+ }
+ if cfg == params.XDCMainnetChainConfig || cfg == params.TestnetChainConfig || cfg == params.DevnetChainConfig {
+ t.Fatalf("expected custom config classification, got built-in pointer: %v", cfg)
+ }
+ if cfg.ChainID == nil || cfg.ChainID.Cmp(big.NewInt(999001)) != 0 {
+ t.Fatalf("unexpected ChainID: have %v want 999001", cfg.ChainID)
+ }
+ if cfg.TIP2019Block == nil || cfg.TIP2019Block.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("expected TIP2019Block to be backfilled to 0, have %v", cfg.TIP2019Block)
+ }
+ if cfg.XDPoS != nil {
+ t.Fatalf("expected no XDPoS backfill for explicit genesis, have %v", cfg.XDPoS)
+ }
+}
+
+func TestSetupGenesisTreatsStoredCustomGenesisWithBuiltInChainIDAsLocalnet(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: new(big.Int).Set(params.XDCMainnetChainConfig.ChainID),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ genesis.MustCommit(db)
+
+ cfg, hash, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if hash != genesis.ToBlock().Hash() {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), genesis.ToBlock().Hash().Hex())
+ }
+ // Only check ChainID and XDPoS.MaxMasternodesV2, do not require all migrated fork fields to be backfilled.
+ if cfg.ChainID.Cmp(params.XDCMainnetChainConfig.ChainID) != 0 {
+ t.Fatalf("unexpected ChainID: have %v want %v", cfg.ChainID, params.XDCMainnetChainConfig.ChainID)
+ }
+ if cfg.XDPoS != nil && cfg.XDPoS.MaxMasternodesV2 != params.LocalnetChainConfig.XDPoS.MaxMasternodesV2 {
+ t.Fatalf("unexpected MaxMasternodesV2: have %v want %v", cfg.XDPoS, params.LocalnetChainConfig.XDPoS.MaxMasternodesV2)
+ }
+}
+
+func TestSetupGenesisAllowsCustomChainWithIntentionallyNilOsakaBlock(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ cfg := params.XDCMainnetChainConfig.Clone()
+ cfg.ChainID = big.NewInt(7778)
+ cfg.XDPoS = nil
+ cfg.Ethash = new(params.EthashConfig)
+ cfg.OsakaBlock = nil
+
+ genesis := &Genesis{
+ Config: cfg,
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ block := genesis.MustCommit(db)
+
+ resolvedCfg, hash, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("SetupGenesisBlock failed: %v", err)
+ }
+ if hash != block.Hash() {
+ t.Fatalf("unexpected genesis hash: have %s want %s", hash.Hex(), block.Hash().Hex())
+ }
+ if resolvedCfg == nil {
+ t.Fatal("expected resolved config")
+ }
+ if resolvedCfg.OsakaBlock != nil {
+ t.Fatalf("expected OsakaBlock to remain nil, have %v", resolvedCfg.OsakaBlock)
+ }
+}
+
+func TestSetupGenesisCustomChainProvidedGenesisThenRestartWithoutGenesis(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ cfg := params.XDCMainnetChainConfig.Clone()
+ cfg.ChainID = big.NewInt(8888)
+ cfg.XDPoS = nil
+ cfg.Ethash = new(params.EthashConfig)
+ cfg.OsakaBlock = nil
+
+ genesis := &Genesis{
+ Config: cfg,
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+
+ initialCfg, hash, _, err := SetupGenesisBlock(db, genesis)
+ if err != nil {
+ t.Fatalf("initial SetupGenesisBlock failed: %v", err)
+ }
+ if initialCfg == nil {
+ t.Fatal("expected initial config")
+ }
+ if initialCfg.OsakaBlock != nil {
+ t.Fatalf("expected OsakaBlock to remain nil after initial setup, have %v", initialCfg.OsakaBlock)
+ }
+
+ restartedCfg, restartedHash, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("restart SetupGenesisBlock failed: %v", err)
+ }
+ if restartedCfg == nil {
+ t.Fatal("expected restart config")
+ }
+ if restartedHash != hash {
+ t.Fatalf("unexpected restart genesis hash: have %s want %s", restartedHash.Hex(), hash.Hex())
+ }
+ if restartedCfg.OsakaBlock != nil {
+ t.Fatalf("expected OsakaBlock to remain nil after restart, have %v", restartedCfg.OsakaBlock)
+ }
+}
+
+func TestLoadChainConfigAllowsLegacyCustomChainWithCompleteMigratedForkFields(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ cfg := params.XDCMainnetChainConfig.Clone()
+ cfg.ChainID = big.NewInt(9898)
+ cfg.XDPoS = nil
+ cfg.Ethash = new(params.EthashConfig)
+
+ genesis := &Genesis{
+ Config: cfg,
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ block := genesis.MustCommit(db)
+
+ loadedCfg, loadedHash, err := LoadChainConfig(db, nil)
+ if err != nil {
+ t.Fatalf("LoadChainConfig failed: %v", err)
+ }
+ if loadedCfg == nil {
+ t.Fatal("expected loaded config")
+ }
+ if loadedHash != block.Hash() {
+ t.Fatalf("unexpected genesis hash: have %s want %s", loadedHash.Hex(), block.Hash().Hex())
+ }
+}
+
+func TestLoadChainConfigUsesStoredBuiltInHashWhenChainConfigMissing(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ block := DefaultTestnetGenesisBlock().ToBlock()
+ rawdb.WriteBlock(db, block)
+ rawdb.WriteHeadHeaderHash(db, block.Hash())
+ rawdb.WriteCanonicalHash(db, block.Hash(), 0)
+ rawdb.WriteChainConfig(db, block.Hash(), params.TestnetChainConfig)
+
+ cfg, hash, err := LoadChainConfig(db, nil)
+ if err != nil {
+ t.Fatalf("LoadChainConfig failed: %v", err)
+ }
+ if hash != params.TestnetGenesisHash {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), params.TestnetGenesisHash.Hex())
+ }
+ if !chainConfigSemanticallyEqual(cfg, params.TestnetChainConfig) {
+ t.Fatalf("unexpected config: have %v want %v", cfg, params.TestnetChainConfig)
+ }
+}
+
+func TestLoadChainConfigReturnsBuiltInConfigInstanceWhenStoredBuiltInConfigMissingFields(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ DefaultTestnetGenesisBlock().MustCommit(db)
+
+ stored := params.TestnetGenesisHash
+ rawCfg, err := rawdb.ReadChainConfigJSON(db, stored)
+ if err != nil {
+ t.Fatalf("failed to read raw chain config: %v", err)
+ }
+ updatedRawCfg, err := removeTopLevelFieldFromRawConfig(rawCfg, "eip1559Block")
+ if err != nil {
+ t.Fatalf("failed to remove eip1559Block from raw config: %v", err)
+ }
+ if err := db.Put(testConfigKey(stored), updatedRawCfg); err != nil {
+ t.Fatalf("failed to write modified raw chain config: %v", err)
+ }
+
+ cfg, hash, err := LoadChainConfig(db, nil)
+ if err != nil {
+ t.Fatalf("LoadChainConfig failed: %v", err)
+ }
+ if hash != stored {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), stored.Hex())
+ }
+ if cfg != params.TestnetChainConfig {
+ t.Fatalf("expected in-memory built-in config instance, have %p want %p", cfg, params.TestnetChainConfig)
+ }
+ if cfg.Eip1559Block == nil {
+ t.Fatalf("expected eip1559Block from built-in config, got nil")
+ }
+}
+
+func TestSetupGenesisBlockReturnsMarshalStoredConfigError(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ DefaultGenesisBlock().MustCommit(db)
+
+ originalMarshal := jsonMarshal
+ defer func() { jsonMarshal = originalMarshal }()
+
+ injectedErr := errors.New("injected marshal failure")
+ callCount := 0
+ jsonMarshal = func(v any) ([]byte, error) {
+ callCount++
+ if callCount == 1 {
+ return nil, injectedErr
+ }
+ return json.Marshal(v)
+ }
+
+ _, _, _, err := SetupGenesisBlock(db, nil)
+ if err == nil {
+ t.Fatal("expected error, got nil")
+ }
+ if !strings.Contains(err.Error(), "failed to marshal stored chain config") {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if !errors.Is(err, injectedErr) {
+ t.Fatalf("expected injected error, got %v", err)
+ }
+}
+
+func TestSetupGenesisBlockReturnsMarshalNewConfigError(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ DefaultGenesisBlock().MustCommit(db)
+
+ originalMarshal := jsonMarshal
+ defer func() { jsonMarshal = originalMarshal }()
+
+ injectedErr := errors.New("injected marshal failure")
+ callCount := 0
+ jsonMarshal = func(v any) ([]byte, error) {
+ callCount++
+ if callCount == 2 {
+ return nil, injectedErr
+ }
+ return json.Marshal(v)
+ }
+
+ _, _, _, err := SetupGenesisBlock(db, nil)
+ if err == nil {
+ t.Fatal("expected error, got nil")
+ }
+ if !strings.Contains(err.Error(), "failed to marshal new chain config") {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if !errors.Is(err, injectedErr) {
+ t.Fatalf("expected injected error, got %v", err)
+ }
+}
+
+func TestSetupGenesisTreatsCustomChainAsLocalnetWhenChainConfigMissing(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ cfg, hash, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if hash != params.MainnetGenesisHash {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), params.MainnetGenesisHash.Hex())
+ }
+ if cfg == nil {
+ t.Fatal("expected resolved config")
+ }
+ assertMigratedForkFieldsEqual(t, cfg, params.XDCMainnetChainConfig)
+}
+
+func TestLoadChainConfigTreatsCustomChainAsLocalnetWhenChainConfigMissing(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ cfg, hash, err := LoadChainConfig(db, nil)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if hash != params.MainnetGenesisHash {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), params.MainnetGenesisHash.Hex())
+ }
+ if cfg == nil {
+ t.Fatal("expected resolved config")
+ }
+ assertMigratedForkFieldsEqual(t, cfg, params.XDCMainnetChainConfig)
+}
+
+func TestGenesisCommitRejectsMissingTIPTRC21FeeBlock(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(31337),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+
+ _, err := genesis.Commit(db)
+ if !errors.Is(err, params.ErrMissingForkSwitch) {
+ t.Fatalf("unexpected error: have %v want %v", err, params.ErrMissingForkSwitch)
+ }
+}
+
+func TestSetupGenesisBackfillsMissingTIPTRC21FeeBlock(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(41414),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+
+ cfg, hash, _, err := SetupGenesisBlock(db, genesis)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if hash == (common.Hash{}) {
+ t.Fatalf("unexpected empty hash")
+ }
+ if cfg == nil || cfg.TIPTRC21FeeBlock == nil || cfg.TIPTRC21FeeBlock.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("expected TIPTRC21FeeBlock to be backfilled to 0, have %v", cfg)
+ }
+}
+
+func TestLoadChainConfigBackfillsMissingTIPTRC21FeeBlock(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(51515),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+
+ cfg, hash, err := LoadChainConfig(db, genesis)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if cfg == nil {
+ t.Fatal("expected resolved config")
+ }
+ if hash == (common.Hash{}) {
+ t.Fatalf("unexpected empty hash")
+ }
+ if cfg.TIPTRC21FeeBlock == nil || cfg.TIPTRC21FeeBlock.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("expected TIPTRC21FeeBlock to be backfilled to 0, have %v", cfg.TIPTRC21FeeBlock)
+ }
+}
+
+func TestLoadChainConfigBackfillsMissingStoredFieldForCustomNetworkReadPath(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(61616),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(12345),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ block := genesis.MustCommit(db)
+
+ rawCfg, err := rawdb.ReadChainConfigJSON(db, block.Hash())
+ if err != nil {
+ t.Fatalf("failed to read raw chain config: %v", err)
+ }
+ updatedRawCfg, err := removeTopLevelFieldFromRawConfig(rawCfg, "gas50xBlock")
+ if err != nil {
+ t.Fatalf("failed to remove gas50xBlock from raw config: %v", err)
+ }
+ if err := db.Put(testConfigKey(block.Hash()), updatedRawCfg); err != nil {
+ t.Fatalf("failed to write modified raw chain config: %v", err)
+ }
+
+ cfg, hash, err := LoadChainConfig(db, nil)
+ if err != nil {
+ t.Fatalf("LoadChainConfig failed: %v", err)
+ }
+ if hash != block.Hash() {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), block.Hash().Hex())
+ }
+ if cfg == nil || cfg.Gas50xBlock == nil {
+ t.Fatalf("expected Gas50xBlock to be backfilled, have %v", cfg)
+ }
+ if cfg.Gas50xBlock.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("unexpected Gas50xBlock: have %v want 0 (Localnet default)", cfg.Gas50xBlock)
+ }
+}
+
+func TestSetupGenesisBackfillsMissingStoredFieldForCustomNetworkReadPath(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(62626),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(12345),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+ block := genesis.MustCommit(db)
+
+ rawCfg, err := rawdb.ReadChainConfigJSON(db, block.Hash())
+ if err != nil {
+ t.Fatalf("failed to read raw chain config: %v", err)
+ }
+ updatedRawCfg, err := removeTopLevelFieldFromRawConfig(rawCfg, "gas50xBlock")
+ if err != nil {
+ t.Fatalf("failed to remove gas50xBlock from raw config: %v", err)
+ }
+ if err := db.Put(testConfigKey(block.Hash()), updatedRawCfg); err != nil {
+ t.Fatalf("failed to write modified raw chain config: %v", err)
+ }
+
+ cfg, hash, _, err := SetupGenesisBlock(db, nil)
+ if err != nil {
+ t.Fatalf("SetupGenesisBlock failed: %v", err)
+ }
+ if hash != block.Hash() {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), block.Hash().Hex())
+ }
+ if cfg == nil || cfg.Gas50xBlock == nil {
+ t.Fatalf("expected Gas50xBlock to be backfilled, have %v", cfg)
+ }
+ if cfg.Gas50xBlock.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("unexpected Gas50xBlock: have %v want 0 (Localnet default)", cfg.Gas50xBlock)
+ }
+}
+
+func TestSetupGenesisBackfillsTIPTRC21FeeBlockForLocalnetChainID(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ genesis := &Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(5151),
+ Ethash: new(params.EthashConfig),
+ },
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1)},
+ },
+ GasLimit: 4700000,
+ Difficulty: big.NewInt(1),
+ }
+
+ cfg, _, _, err := SetupGenesisBlock(db, genesis)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if cfg == nil || cfg.TIPTRC21FeeBlock == nil || cfg.TIPTRC21FeeBlock.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("expected TIPTRC21FeeBlock to be backfilled to 0, have %v", cfg)
+ }
+}
+
func TestSetupGenesis(t *testing.T) {
var (
- customghash = common.HexToHash("0xfc8a143549950b0d3e3e7b70b0067b152e6b903ab5438f1ea87f0448ec93da48")
- customg = Genesis{
- Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)},
+ customg = Genesis{
+ Config: ¶ms.ChainConfig{
+ ChainID: big.NewInt(4444),
+ HomesteadBlock: big.NewInt(3),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ Ethash: new(params.EthashConfig),
+ },
Alloc: types.GenesisAlloc{
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
},
}
- oldcustomg = customg
+ oldcustomg = customg
+ configReadErr = errors.New("chain config read failed")
)
- oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)}
+ canonicalCustomCfg := canonicalizeChainConfig(common.Hash{}, customg.Config)
+ customg.Config = canonicalCustomCfg.Clone()
+ customghash := customg.ToBlock().Hash()
+ oldcustomg.Config = ¶ms.ChainConfig{ChainID: big.NewInt(4444), HomesteadBlock: big.NewInt(2), TIPTRC21FeeBlock: big.NewInt(0), Ethash: new(params.EthashConfig)}
+ oldcustomg.Config = canonicalizeChainConfig(common.Hash{}, oldcustomg.Config)
tests := []struct {
- name string
- fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error)
- wantConfig *params.ChainConfig
- wantHash common.Hash
- wantErr error
+ name string
+ fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error, error)
+ wantConfig *params.ChainConfig
+ wantHash common.Hash
+ wantErr error
+ wantCompactErr *params.ConfigCompatError
}{
{
name: "genesis without ChainConfig",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
return SetupGenesisBlock(db, new(Genesis))
},
wantErr: errGenesisNoConfig,
- wantConfig: params.AllEthashProtocolChanges,
+ wantConfig: nil,
},
{
name: "no block in DB, genesis == nil",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
return SetupGenesisBlock(db, nil)
},
wantHash: params.MainnetGenesisHash,
@@ -81,7 +1062,7 @@ func TestSetupGenesis(t *testing.T) {
},
{
name: "mainnet block in DB, genesis == nil",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
DefaultGenesisBlock().MustCommit(db)
return SetupGenesisBlock(db, nil)
},
@@ -90,37 +1071,37 @@ func TestSetupGenesis(t *testing.T) {
},
{
name: "custom block in DB, genesis == nil",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
customg.MustCommit(db)
return SetupGenesisBlock(db, nil)
},
wantHash: customghash,
- wantConfig: customg.Config,
+ wantConfig: canonicalCustomCfg,
},
{
name: "custom block in DB, genesis == testnet",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
customg.MustCommit(db)
return SetupGenesisBlock(db, DefaultTestnetGenesisBlock())
},
wantErr: &GenesisMismatchError{Stored: customghash, New: params.TestnetGenesisHash},
- wantHash: params.TestnetGenesisHash,
- wantConfig: params.TestnetChainConfig,
+ wantHash: common.Hash{},
+ wantConfig: nil,
},
{
name: "stored canonical hash without header",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
missingHash := common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
rawdb.WriteCanonicalHash(db, missingHash, 0)
return SetupGenesisBlock(db, nil)
},
wantErr: fmt.Errorf("missing genesis header for hash: %s", common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Hex()),
wantHash: common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
- wantConfig: params.AllEthashProtocolChanges,
+ wantConfig: nil,
},
{
name: "genesis header present but state missing",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
block := DefaultGenesisBlock().ToBlock()
rawdb.WriteCanonicalHash(db, block.Hash(), 0)
rawdb.WriteHeader(db, block.Header())
@@ -131,7 +1112,7 @@ func TestSetupGenesis(t *testing.T) {
},
{
name: "genesis block without chain config",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
block := DefaultGenesisBlock().ToBlock()
rawdb.WriteBlock(db, block)
rawdb.WriteCanonicalHash(db, block.Hash(), 0)
@@ -140,9 +1121,25 @@ func TestSetupGenesis(t *testing.T) {
wantHash: params.MainnetGenesisHash,
wantConfig: params.XDCMainnetChainConfig,
},
+ {
+ name: "chain config read error does not trigger recovery",
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
+ block := DefaultGenesisBlock().MustCommit(db)
+ brokenDB := &failingConfigReadDB{
+ Database: db,
+ targetKey: testConfigKey(block.Hash()),
+ getErr: configReadErr,
+ hasResult: true,
+ }
+ return SetupGenesisBlock(brokenDB, nil)
+ },
+ wantErr: fmt.Errorf("failed to read chain config for hash %s: %w", params.MainnetGenesisHash.Hex(), configReadErr),
+ wantHash: common.Hash{},
+ wantConfig: nil,
+ },
{
name: "missing block number for head header hash",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
DefaultGenesisBlock().MustCommit(db)
rawdb.WriteHeadHeaderHash(db, common.HexToHash("0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
return SetupGenesisBlock(db, nil)
@@ -153,32 +1150,41 @@ func TestSetupGenesis(t *testing.T) {
},
{
name: "compatible config in DB",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
oldcustomg.MustCommit(db)
- return SetupGenesisBlock(db, &customg)
+ genesis := customg
+ genesis.Config = customg.Config.Clone()
+ return SetupGenesisBlock(db, &genesis)
},
wantHash: customghash,
- wantConfig: customg.Config,
+ wantConfig: canonicalCustomCfg,
},
{
name: "incompatible config in DB",
- fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error, error) {
// Commit the 'old' genesis block with Homestead transition at #2.
// Advance to block #4, past the homestead transition block of customg.
genesis := oldcustomg.MustCommit(db)
- bc, _ := NewBlockChain(db, nil, &oldcustomg, ethash.NewFullFaker(), vm.Config{})
+ bc, err := NewBlockChain(db, nil, &oldcustomg, ethash.NewFullFaker(), vm.Config{})
+ if err != nil {
+ return nil, common.Hash{}, err, nil
+ }
defer bc.Stop()
blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)
- bc.InsertChain(blocks)
+ if _, err := bc.InsertChain(blocks); err != nil {
+ return nil, common.Hash{}, err, nil
+ }
bc.CurrentBlock()
// This should return a compatibility error.
- return SetupGenesisBlock(db, &customg)
+ genesisCfg := customg
+ genesisCfg.Config = customg.Config.Clone()
+ return SetupGenesisBlock(db, &genesisCfg)
},
wantHash: customghash,
- wantConfig: customg.Config,
- wantErr: ¶ms.ConfigCompatError{
+ wantConfig: canonicalCustomCfg,
+ wantCompactErr: ¶ms.ConfigCompatError{
What: "Homestead fork block",
StoredConfig: big.NewInt(2),
NewConfig: big.NewInt(3),
@@ -187,16 +1193,92 @@ func TestSetupGenesis(t *testing.T) {
},
}
+ // Only compare fields explicitly set in the user's original config and required backfilled fields
+ chainConfigSemanticallyEqual := func(a, b *params.ChainConfig) bool {
+ if a == nil || b == nil {
+ return a == b
+ }
+ va := reflect.ValueOf(a).Elem()
+ vb := reflect.ValueOf(b).Elem()
+ fields := []string{"ChainID", "TIPTRC21FeeBlock", "XDPoS"}
+ // Add non-nil fields from b (only call IsNil on types that support it)
+ nilKinds := map[reflect.Kind]bool{
+ reflect.Pointer: true, reflect.Slice: true, reflect.Map: true, reflect.Chan: true, reflect.Func: true, reflect.Interface: true,
+ }
+ typeOfCfg := va.Type()
+ for i := 0; i < vb.NumField(); i++ {
+ fname := typeOfCfg.Field(i).Name
+ if slices.Contains(fields, fname) {
+ continue
+ }
+ fieldVal := vb.Field(i)
+ if nilKinds[fieldVal.Kind()] && !fieldVal.IsNil() {
+ fields = append(fields, fname)
+ }
+ }
+ for _, fname := range fields {
+ fa := va.FieldByName(fname)
+ fb := vb.FieldByName(fname)
+ if !fa.IsValid() || !fb.IsValid() {
+ return false
+ }
+ // For *big.Int pointers
+ if fa.Type().String() == "*big.Int" {
+ if fa.Kind() == reflect.Ptr && fb.Kind() == reflect.Ptr {
+ if (fa.IsNil() && !fb.IsNil()) || (!fa.IsNil() && fb.IsNil()) {
+ return false
+ }
+ if !fa.IsNil() && fa.Interface().(*big.Int).Cmp(fb.Interface().(*big.Int)) != 0 {
+ return false
+ }
+ continue
+ }
+ }
+ // For XDPoS field
+ if fname == "XDPoS" {
+ if !params.XDPoSConfigEqual(fa.Interface().(*params.XDPoSConfig), fb.Interface().(*params.XDPoSConfig)) {
+ return false
+ }
+ continue
+ }
+ // Only call IsNil on types that support it
+ nilKinds := map[reflect.Kind]bool{
+ reflect.Ptr: true, reflect.Slice: true, reflect.Map: true, reflect.Chan: true, reflect.Func: true, reflect.Interface: true,
+ }
+ if !nilKinds[fa.Kind()] {
+ if !reflect.DeepEqual(fa.Interface(), fb.Interface()) {
+ return false
+ }
+ continue
+ }
+ // Only proceed if both sides support IsNil
+ if fa.IsNil() != fb.IsNil() {
+ return false
+ }
+ if fa.IsNil() && fb.IsNil() {
+ continue
+ }
+ if !reflect.DeepEqual(fa.Interface(), fb.Interface()) {
+ return false
+ }
+ }
+ return true
+ }
+
for _, test := range tests {
db := rawdb.NewMemoryDatabase()
- config, hash, err := test.fn(db)
+ config, hash, compatErr, err := test.fn(db)
// Check the return values.
- if (err == nil) != (test.wantErr == nil) || (err != nil && test.wantErr != nil && !errors.Is(err, test.wantErr) && err.Error() != test.wantErr.Error()) {
+ if !chainConfigSemanticallyEqual(config, test.wantConfig) {
+ t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig)
+ }
+ if !reflect.DeepEqual(err, test.wantErr) {
spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
}
- if !reflect.DeepEqual(config, test.wantConfig) {
- t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig)
+ if !reflect.DeepEqual(compatErr, test.wantCompactErr) {
+ spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
+ t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(compatErr), spew.NewFormatter(test.wantCompactErr))
}
if hash != test.wantHash {
t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
@@ -209,3 +1291,48 @@ func TestSetupGenesis(t *testing.T) {
}
}
}
+
+func TestSetupGenesisConfigCompatibilityPathReturnsConfig(t *testing.T) {
+ customg := Genesis{
+ Config: ¶ms.ChainConfig{ChainID: big.NewInt(4444), HomesteadBlock: big.NewInt(3), TIPTRC21FeeBlock: big.NewInt(0), Ethash: new(params.EthashConfig)},
+ Alloc: types.GenesisAlloc{
+ {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
+ },
+ }
+ oldcustomg := customg
+ oldcustomg.Config = ¶ms.ChainConfig{ChainID: big.NewInt(4444), HomesteadBlock: big.NewInt(2), TIPTRC21FeeBlock: big.NewInt(0), Ethash: new(params.EthashConfig)}
+ customg.Config = canonicalizeChainConfig(common.Hash{}, customg.Config)
+ oldcustomg.Config = canonicalizeChainConfig(common.Hash{}, oldcustomg.Config)
+
+ db := rawdb.NewMemoryDatabase()
+ genesis := oldcustomg.MustCommit(db)
+
+ bc, err := NewBlockChain(db, nil, &oldcustomg, ethash.NewFullFaker(), vm.Config{})
+ if err != nil {
+ t.Fatalf("failed to create blockchain: %v", err)
+ }
+ defer bc.Stop()
+
+ blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)
+ if _, err := bc.InsertChain(blocks); err != nil {
+ t.Fatalf("failed to insert chain: %v", err)
+ }
+
+ config, hash, compatErr, gotErr := SetupGenesisBlock(db, &customg)
+ if compatErr == nil {
+ t.Fatal("expected compatibility error")
+ }
+ if compatErr.What != "Homestead fork block" || compatErr.RewindTo != 1 {
+ t.Fatalf("unexpected compatibility error: %v", compatErr)
+ }
+ if gotErr != nil {
+ t.Fatalf("unexpected setup error: have %v want ConfigCompatError", gotErr)
+ }
+ if config == nil {
+ t.Fatal("unexpected nil config")
+ }
+ wantHash := genesis.Hash()
+ if hash != wantHash {
+ t.Fatalf("unexpected hash: have %s want %s", hash.Hex(), wantHash.Hex())
+ }
+}
diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go
index c944e910abc0..0d1c0f274d21 100644
--- a/core/rawdb/accessors_chain_test.go
+++ b/core/rawdb/accessors_chain_test.go
@@ -19,6 +19,7 @@ package rawdb
import (
"bytes"
"encoding/hex"
+ "errors"
"fmt"
"math/big"
"math/rand/v2"
@@ -33,6 +34,50 @@ import (
"github.com/XinFinOrg/XDPoSChain/rlp"
)
+type errorReader struct {
+ hasResult bool
+ hasErr error
+ getErr error
+ value []byte
+}
+
+func (r *errorReader) Has(key []byte) (bool, error) {
+ return r.hasResult, r.hasErr
+}
+
+func (r *errorReader) Get(key []byte) ([]byte, error) {
+ if r.getErr != nil {
+ return nil, r.getErr
+ }
+ return r.value, nil
+}
+
+func TestReadChainConfigGetError(t *testing.T) {
+ hash := common.HexToHash("0x1")
+ wantErr := errors.New("boom")
+ _, err := ReadChainConfig(&errorReader{getErr: wantErr, hasResult: true}, hash)
+ if !errors.Is(err, wantErr) {
+ t.Fatalf("expected wrapped get error, got %v", err)
+ }
+}
+
+func TestReadChainConfigNotFound(t *testing.T) {
+ hash := common.HexToHash("0x2")
+ _, err := ReadChainConfig(&errorReader{getErr: errors.New("missing"), hasResult: false}, hash)
+ if !errors.Is(err, ErrChainConfigNotFound) {
+ t.Fatalf("expected ErrChainConfigNotFound, got %v", err)
+ }
+}
+
+func TestReadChainConfigJSONGetError(t *testing.T) {
+ hash := common.HexToHash("0x3")
+ wantErr := errors.New("boom")
+ _, err := ReadChainConfigJSON(&errorReader{getErr: wantErr, hasResult: true}, hash)
+ if !errors.Is(err, wantErr) {
+ t.Fatalf("expected wrapped get error, got %v", err)
+ }
+}
+
type fullLogRLP struct {
Address common.Address
Topics []common.Hash
diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go
index efb6b0c68383..17ab94534a18 100644
--- a/core/rawdb/accessors_metadata.go
+++ b/core/rawdb/accessors_metadata.go
@@ -28,6 +28,23 @@ import (
"github.com/XinFinOrg/XDPoSChain/rlp"
)
+var ErrChainConfigNotFound = errors.New("chain config not found")
+
+func readOptionalBlob(db ethdb.KeyValueReader, key []byte) ([]byte, error) {
+ blob, err := db.Get(key)
+ if err == nil {
+ return blob, nil
+ }
+ has, hasErr := db.Has(key)
+ if hasErr == nil && !has {
+ return nil, ErrChainConfigNotFound
+ }
+ if hasErr != nil {
+ return nil, fmt.Errorf("get failed: %w (has failed: %v)", err, hasErr)
+ }
+ return nil, err
+}
+
// ReadDatabaseVersion retrieves the version number of the database.
func ReadDatabaseVersion(db ethdb.KeyValueReader) *uint64 {
var version uint64
@@ -56,9 +73,15 @@ func WriteDatabaseVersion(db ethdb.KeyValueWriter, version uint64) {
// ReadChainConfig will fetch the network settings based on the given hash.
func ReadChainConfig(db ethdb.KeyValueReader, hash common.Hash) (*params.ChainConfig, error) {
- jsonChainConfig, _ := db.Get(configKey(hash))
+ jsonChainConfig, err := readOptionalBlob(db, configKey(hash))
+ if err != nil {
+ if errors.Is(err, ErrChainConfigNotFound) {
+ return nil, err
+ }
+ return nil, fmt.Errorf("failed to read chain config for hash %s: %w", hash.Hex(), err)
+ }
if len(jsonChainConfig) == 0 {
- return nil, errors.New("ChainConfig not found") // general config not found error
+ return nil, ErrChainConfigNotFound
}
var config params.ChainConfig
@@ -70,6 +93,15 @@ func ReadChainConfig(db ethdb.KeyValueReader, hash common.Hash) (*params.ChainCo
return &config, nil
}
+// ReadChainConfigJSON fetches the raw JSON chain config blob for the given hash.
+func ReadChainConfigJSON(db ethdb.KeyValueReader, hash common.Hash) ([]byte, error) {
+ jsonChainConfig, err := readOptionalBlob(db, configKey(hash))
+ if err != nil {
+ return nil, err
+ }
+ return jsonChainConfig, nil
+}
+
// WriteChainConfig writes the chain config settings to the database.
func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.ChainConfig) {
if cfg == nil {
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 922b663ec835..c6a82033f479 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -110,6 +110,8 @@ type StateDB struct {
// when accessing state of accounts.
dbErr error
+ chainConfig *params.ChainConfig
+
// The refund counter, also used by state transitioning.
refund uint64
@@ -196,6 +198,42 @@ func (s *StateDB) Error() error {
return s.dbErr
}
+func (s *StateDB) SetChainConfig(config *params.ChainConfig) {
+ s.chainConfig = config
+}
+
+func (s *StateDB) ChainConfig() *params.ChainConfig {
+ return s.chainConfig
+}
+
+func (s *StateDB) TRC21IssuerSMC() common.Address {
+ if s.chainConfig == nil {
+ return common.Address{}
+ }
+ return s.chainConfig.TRC21IssuerSMC
+}
+
+func (s *StateDB) XDCXListingSMC() common.Address {
+ if s.chainConfig == nil {
+ return common.Address{}
+ }
+ return s.chainConfig.XDCXListingSMC
+}
+
+func (s *StateDB) RelayerRegistrationSMC() common.Address {
+ if s.chainConfig == nil {
+ return common.Address{}
+ }
+ return s.chainConfig.RelayerRegistrationSMC
+}
+
+func (s *StateDB) LendingRegistrationSMC() common.Address {
+ if s.chainConfig == nil {
+ return common.Address{}
+ }
+ return s.chainConfig.LendingRegistrationSMC
+}
+
// Reset clears out all ephemeral state objects from the state db, but keeps
// the underlying state trie to avoid reloading data for the next operations.
func (s *StateDB) Reset(root common.Hash) error {
@@ -747,6 +785,7 @@ func (s *StateDB) Copy() *StateDB {
stateObjectsDestruct: maps.Clone(s.stateObjectsDestruct),
mutations: make(map[common.Address]*mutation, len(s.mutations)),
dbErr: s.dbErr,
+ chainConfig: s.chainConfig,
refund: s.refund,
thash: s.thash,
txIndex: s.txIndex,
diff --git a/core/state/trc21_reader.go b/core/state/trc21_reader.go
index 549655fbf8f9..8733d7deda90 100644
--- a/core/state/trc21_reader.go
+++ b/core/state/trc21_reader.go
@@ -49,17 +49,18 @@ func (s *StateDB) GetTRC21FeeCapacityFromState() map[common.Address]*big.Int {
}
tokensCapacity := map[common.Address]*big.Int{}
+ issuer := s.TRC21IssuerSMC()
slotTokens := SlotTRC21Issuer["tokens"]
slotTokensHash := common.BigToHash(new(big.Int).SetUint64(slotTokens))
slotTokensState := SlotTRC21Issuer["tokensState"]
- tokenCount := s.GetState(common.TRC21IssuerSMC, slotTokensHash).Big().Uint64()
+ tokenCount := s.GetState(issuer, slotTokensHash).Big().Uint64()
for i := range tokenCount {
key := GetLocDynamicArrAtElement(slotTokensHash, i, 1)
- value := s.GetState(common.TRC21IssuerSMC, key)
+ value := s.GetState(issuer, key)
if !value.IsZero() {
token := common.BytesToAddress(value.Bytes())
balanceKey := GetLocMappingAtKey(token.Hash(), slotTokensState)
- balanceHash := s.GetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey))
+ balanceHash := s.GetState(issuer, common.BigToHash(balanceKey))
tokensCapacity[common.BytesToAddress(token.Bytes())] = balanceHash.Big()
}
}
@@ -151,9 +152,10 @@ func (s *StateDB) UpdateTRC21Fee(newBalance map[common.Address]*big.Int, totalFe
}
slotTokensState := SlotTRC21Issuer["tokensState"]
+ issuer := s.TRC21IssuerSMC()
for token, value := range newBalance {
balanceKey := GetLocMappingAtKey(token.Hash(), slotTokensState)
- s.SetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey), common.BigToHash(value))
+ s.SetState(issuer, common.BigToHash(balanceKey), common.BigToHash(value))
}
- s.SubBalance(common.TRC21IssuerSMC, totalFeeUsed, tracing.BalanceChangeUnspecified)
+ s.SubBalance(issuer, totalFeeUsed, tracing.BalanceChangeUnspecified)
}
diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go
index eee1e5aba0aa..af4849158955 100644
--- a/core/state_prefetcher.go
+++ b/core/state_prefetcher.go
@@ -63,7 +63,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
return
}
// Convert the transaction into an executable message and pre-cache its sender
- msg, err := TransactionToMessage(tx, signer, nil, nil, header.BaseFee)
+ msg, err := TransactionToMessage(tx, signer, nil, nil, header.BaseFee, p.config)
if err != nil {
return // Also invalid block, bail out
}
diff --git a/core/state_processor.go b/core/state_processor.go
index 3ed93362d786..8c187fa62147 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -68,6 +68,7 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen
// returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error.
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tradingState *tradingstate.TradingStateDB, cfg vm.Config, tokensFee map[common.Address]*big.Int) (types.Receipts, []*types.Log, uint64, error) {
+ statedb.SetChainConfig(p.config)
var (
receipts = make([]*types.Receipt, 0, len(block.Transactions()))
usedGas = new(uint64)
@@ -87,7 +88,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(tracingStateDB)
}
- if common.TIPSigning.Cmp(blockNumber) == 0 {
+ if p.config.TIPSigningBlock != nil && p.config.TIPSigningBlock.Cmp(blockNumber) == 0 {
statedb.DeleteAddress(common.BlockSignersBinary)
}
parentState := statedb.Copy()
@@ -107,7 +108,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
// check denylist txs after hf
- if block.Number().Uint64() >= common.DenylistHFNumber {
+ if p.config.IsDenylist(block.Number()) {
// check if sender is in denylist
if common.IsInDenylist(tx.From()) {
return nil, nil, 0, fmt.Errorf("block contains transaction with sender in denylist: %v", tx.From().Hex())
@@ -118,14 +119,14 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
}
}
// validate minFee slot for XDCZ
- if tx.IsXDCZApplyTransaction() {
+ if tx.IsXDCZApplyTransaction(p.config) {
copyState := statedb.Copy()
if err := ValidateXDCZApplyTransaction(p.bc, block.Number(), copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
return nil, nil, 0, err
}
}
// validate balance slot, token decimal for XDCX
- if tx.IsXDCXApplyTransaction() {
+ if tx.IsXDCXApplyTransaction(p.config) {
copyState := statedb.Copy()
if err := ValidateXDCXApplyTransaction(p.bc, block.Number(), copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
return nil, nil, 0, err
@@ -138,7 +139,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
balanceFee = value
}
}
- msg, err := TransactionToMessage(tx, signer, balanceFee, blockNumber, header.BaseFee)
+ msg, err := TransactionToMessage(tx, signer, balanceFee, blockNumber, header.BaseFee, p.config)
if err != nil {
return nil, nil, 0, err
}
@@ -151,7 +152,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
if tokenFeeUsed {
- fee := common.GetGasFee(block.Header().Number.Uint64(), gas)
+ fee := common.GetGasFee(block.Header().Number.Uint64(), gas, p.config.TIPTRC21FeeBlock, p.config.Gas50xBlock)
tokensFee[*tx.To()] = new(big.Int).Sub(tokensFee[*tx.To()], fee)
balanceUpdated[*tx.To()] = tokensFee[*tx.To()]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
@@ -166,6 +167,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
}
func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, statedb *state.StateDB, tradingState *tradingstate.TradingStateDB, cfg vm.Config, tokensFee map[common.Address]*big.Int) (types.Receipts, []*types.Log, uint64, error) {
+ statedb.SetChainConfig(p.config)
block := cBlock.block
var (
receipts types.Receipts
@@ -186,7 +188,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(tracingStateDB)
}
- if common.TIPSigning.Cmp(blockNumber) == 0 {
+ if p.config.TIPSigningBlock != nil && p.config.TIPSigningBlock.Cmp(blockNumber) == 0 {
statedb.DeleteAddress(common.BlockSignersBinary)
}
if cBlock.stop {
@@ -214,7 +216,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
receipts = make([]*types.Receipt, block.Transactions().Len())
for i, tx := range block.Transactions() {
// check denylist txs after hf
- if block.Number().Uint64() >= common.DenylistHFNumber {
+ if p.config.IsDenylist(block.Number()) {
// check if sender is in denylist
if common.IsInDenylist(tx.From()) {
return nil, nil, 0, fmt.Errorf("block contains transaction with sender in denylist: %v", tx.From().Hex())
@@ -225,14 +227,14 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
}
}
// validate minFee slot for XDCZ
- if tx.IsXDCZApplyTransaction() {
+ if tx.IsXDCZApplyTransaction(p.config) {
copyState := statedb.Copy()
if err := ValidateXDCZApplyTransaction(p.bc, block.Number(), copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
return nil, nil, 0, err
}
}
// validate balance slot, token decimal for XDCX
- if tx.IsXDCXApplyTransaction() {
+ if tx.IsXDCXApplyTransaction(p.config) {
copyState := statedb.Copy()
if err := ValidateXDCXApplyTransaction(p.bc, block.Number(), copyState, common.BytesToAddress(tx.Data()[4:])); err != nil {
return nil, nil, 0, err
@@ -244,7 +246,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
balanceFee = value
}
}
- msg, err := TransactionToMessage(tx, signer, balanceFee, blockNumber, header.BaseFee)
+ msg, err := TransactionToMessage(tx, signer, balanceFee, blockNumber, header.BaseFee, p.config)
if err != nil {
return nil, nil, 0, err
}
@@ -260,7 +262,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
receipts[i] = receipt
allLogs = append(allLogs, receipt.Logs...)
if tokenFeeUsed {
- fee := common.GetGasFee(block.Header().Number.Uint64(), gas)
+ fee := common.GetGasFee(block.Header().Number.Uint64(), gas, p.config.TIPTRC21FeeBlock, p.config.Gas50xBlock)
tokensFee[*tx.To()] = new(big.Int).Sub(tokensFee[*tx.To()], fee)
balanceUpdated[*tx.To()] = tokensFee[*tx.To()]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
@@ -374,7 +376,7 @@ func ApplyTransaction(tokensFee map[common.Address]*big.Int, evm *vm.EVM, gp *Ga
}
signer := types.MakeSigner(evm.ChainConfig(), header.Number)
- msg, err := TransactionToMessage(tx, signer, balanceFee, header.Number, header.BaseFee)
+ msg, err := TransactionToMessage(tx, signer, balanceFee, header.Number, header.BaseFee, evm.ChainConfig())
if err != nil {
return nil, 0, false, err
}
@@ -505,9 +507,6 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
return
}
forkBlock := evm.ChainConfig().PragueBlock
- if forkBlock == nil {
- forkBlock = common.PragueBlock
- }
if forkBlock == nil || blockNumber.Cmp(forkBlock) < 0 {
return
}
diff --git a/core/state_processor_test.go b/core/state_processor_test.go
index 0af690f58170..9ab94738fde4 100644
--- a/core/state_processor_test.go
+++ b/core/state_processor_test.go
@@ -23,6 +23,7 @@ import (
"fmt"
"math"
"math/big"
+ "strings"
"testing"
"github.com/XinFinOrg/XDPoSChain/common"
@@ -57,6 +58,7 @@ func TestStateProcessorErrors(t *testing.T) {
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ShanghaiBlock: big.NewInt(0),
@@ -295,8 +297,9 @@ func TestStateProcessorErrors(t *testing.T) {
// ErrTxTypeNotSupported, For this, we need an older chain
{
var (
- db = rawdb.NewMemoryDatabase()
- gspec = &Genesis{
+ db = rawdb.NewMemoryDatabase()
+ futureFork = big.NewInt(1_000_000_000)
+ gspec = &Genesis{
Config: ¶ms.ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
@@ -307,6 +310,15 @@ func TestStateProcessorErrors(t *testing.T) {
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: new(big.Int).Set(futureFork),
+ LondonBlock: new(big.Int).Set(futureFork),
+ MergeBlock: new(big.Int).Set(futureFork),
+ ShanghaiBlock: new(big.Int).Set(futureFork),
+ Eip1559Block: new(big.Int).Set(futureFork),
+ CancunBlock: new(big.Int).Set(futureFork),
+ PragueBlock: new(big.Int).Set(futureFork),
+ OsakaBlock: new(big.Int).Set(futureFork),
},
Alloc: types.GenesisAlloc{
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{
@@ -341,6 +353,86 @@ func TestStateProcessorErrors(t *testing.T) {
}
}
+func TestStateProcessorDenylistHardForkBoundary(t *testing.T) {
+ testDenylistedReceiver := common.HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd")
+ if !common.IsInDenylist(&testDenylistedReceiver) {
+ t.Fatalf("test receiver is not denylisted: %v", testDenylistedReceiver.Hex())
+ }
+
+ key, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ if err != nil {
+ t.Fatalf("failed to parse test key: %v", err)
+ }
+ from := crypto.PubkeyToAddress(key.PublicKey)
+
+ newConfig := func(forkBlock uint64) *params.ChainConfig {
+ return ¶ms.ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DenylistBlock: new(big.Int).SetUint64(forkBlock),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ OsakaBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: nil,
+ Ethash: new(params.EthashConfig),
+ }
+ }
+
+ run := func(t *testing.T, forkBlock uint64, expectDenylistErr bool) {
+ t.Helper()
+
+ cfg := newConfig(forkBlock)
+ signer := types.LatestSigner(cfg)
+ tx, err := types.SignTx(types.NewTransaction(0, testDenylistedReceiver, big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, key)
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+
+ gspec := &Genesis{
+ Config: cfg,
+ Alloc: types.GenesisAlloc{
+ from: {
+ Balance: big.NewInt(1_000_000_000_000_000_000),
+ Nonce: 0,
+ },
+ },
+ }
+ db := rawdb.NewMemoryDatabase()
+ blockchain, _ := NewBlockChain(db, nil, gspec, ethash.NewFaker(), vm.Config{})
+ defer blockchain.Stop()
+
+ block := GenerateBadBlock(t, gspec.ToBlock(), ethash.NewFaker(), []*types.Transaction{tx}, cfg)
+ _, err = blockchain.InsertChain(types.Blocks{block})
+ if err == nil {
+ t.Fatal("expected block import error")
+ }
+
+ hasDenylistErr := strings.Contains(err.Error(), "receiver in denylist")
+ if hasDenylistErr != expectDenylistErr {
+ t.Fatalf("unexpected denylist error presence (fork=%d): have=%v err=%v", forkBlock, hasDenylistErr, err)
+ }
+ }
+
+ t.Run("below hardfork does not trigger denylist guard", func(t *testing.T) {
+ run(t, 2, false)
+ })
+ t.Run("at hardfork triggers denylist guard", func(t *testing.T) {
+ run(t, 1, true)
+ })
+}
+
// GenerateBadBlock constructs a "block" which contains the transactions. The transactions are not expected to be
// valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently
// valid to be considered for import:
@@ -397,6 +489,7 @@ func TestApplyTransactionWithEVMTracer(t *testing.T) {
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Eip1559Block: big.NewInt(0),
@@ -485,7 +578,7 @@ func TestApplyTransactionWithEVMTracer(t *testing.T) {
Tracer: mockTracer,
}
- msg, err := TransactionToMessage(signedTx, signer, nil, nil, nil)
+ msg, err := TransactionToMessage(signedTx, signer, nil, nil, nil, config)
if err != nil {
t.Fatalf("Failed to create message: %v", err)
}
@@ -533,6 +626,7 @@ func TestApplyTransactionWithEVMStateChangeHooks(t *testing.T) {
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Eip1559Block: big.NewInt(0),
@@ -580,7 +674,7 @@ func TestApplyTransactionWithEVMStateChangeHooks(t *testing.T) {
vmContext := NewEVMBlockContext(blockchain.CurrentBlock(), blockchain, nil)
evmenv := vm.NewEVM(vmContext, hookedState, nil, blockchain.Config(), vm.Config{Tracer: hooks})
- msg, err := TransactionToMessage(signedTx, signer, nil, big.NewInt(1), nil)
+ msg, err := TransactionToMessage(signedTx, signer, nil, big.NewInt(1), nil, config)
if err != nil {
t.Fatalf("Failed to build message: %v", err)
}
@@ -608,6 +702,7 @@ func TestApplyTransactionWithEVMOnTxStartUsesExecutionGasPrice(t *testing.T) {
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Eip1559Block: big.NewInt(0),
@@ -665,7 +760,7 @@ func TestApplyTransactionWithEVMOnTxStartUsesExecutionGasPrice(t *testing.T) {
},
}
- msg, err := TransactionToMessage(signedTx, signer, nil, big.NewInt(1), nil)
+ msg, err := TransactionToMessage(signedTx, signer, nil, big.NewInt(1), nil, config)
if err != nil {
t.Fatalf("Failed to build message: %v", err)
}
@@ -695,12 +790,21 @@ func TestApplyTransactionWithEVMRejectsValueOverflow(t *testing.T) {
t.Parallel()
config := ¶ms.ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- Ethash: new(params.EthashConfig),
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(1_000_000_000),
+ LondonBlock: big.NewInt(1_000_000_000),
+ MergeBlock: big.NewInt(1_000_000_000),
+ ShanghaiBlock: big.NewInt(1_000_000_000),
+ Eip1559Block: big.NewInt(1_000_000_000),
+ CancunBlock: big.NewInt(1_000_000_000),
+ PragueBlock: big.NewInt(1_000_000_000),
+ OsakaBlock: big.NewInt(1_000_000_000),
+ Ethash: new(params.EthashConfig),
}
signer := types.LatestSigner(config)
key, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@@ -734,7 +838,7 @@ func TestApplyTransactionWithEVMRejectsValueOverflow(t *testing.T) {
if err != nil {
t.Fatalf("Failed to sign tx: %v", err)
}
- msg, err := TransactionToMessage(signedTx, signer, nil, big.NewInt(1), nil)
+ msg, err := TransactionToMessage(signedTx, signer, nil, big.NewInt(1), nil, config)
if err != nil {
t.Fatalf("Failed to build message: %v", err)
}
@@ -814,6 +918,63 @@ func TestProcessParentBlockHashPragueGuard(t *testing.T) {
}
}
+func TestTransactionToMessageRejectsMissingTokenFeeConfig(t *testing.T) {
+ config := params.TestChainConfig.Clone()
+ signer := types.LatestSigner(config)
+ key, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ if err != nil {
+ t.Fatalf("failed to create key: %v", err)
+ }
+ recipient := common.HexToAddress("0x1234567890123456789012345678901234567890")
+ tx := types.NewTransaction(0, recipient, big.NewInt(1), 21000, big.NewInt(1), nil)
+ signedTx, err := types.SignTx(tx, signer, key)
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+
+ tests := []struct {
+ name string
+ cfg *params.ChainConfig
+ errContains string
+ }{
+ {
+ name: "nil chain config",
+ cfg: nil,
+ errContains: "missing chain config",
+ },
+ {
+ name: "nil gas50x block",
+ cfg: func() *params.ChainConfig {
+ cfg := params.TestChainConfig.Clone()
+ cfg.Gas50xBlock = nil
+ return cfg
+ }(),
+ errContains: "missing Gas50xBlock",
+ },
+ {
+ name: "nil trc21 fee block",
+ cfg: func() *params.ChainConfig {
+ cfg := params.TestChainConfig.Clone()
+ cfg.TIPTRC21FeeBlock = nil
+ return cfg
+ }(),
+ errContains: "missing TIPTRC21FeeBlock",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ _, err := TransactionToMessage(signedTx, signer, big.NewInt(1), big.NewInt(1), nil, tt.cfg)
+ if err == nil {
+ t.Fatal("expected error, got nil")
+ }
+ if !strings.Contains(err.Error(), tt.errContains) {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ })
+ }
+}
+
func TestProcessParentBlockHashBackfillMissingHistory(t *testing.T) {
config := *params.MergedTestChainConfig
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())))
diff --git a/core/state_transition.go b/core/state_transition.go
index 388a84185c8b..d1e861906cba 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -18,6 +18,7 @@ package core
import (
"bytes"
+ "errors"
"fmt"
"math"
"math/big"
@@ -158,7 +159,7 @@ type Message struct {
}
// TransactionToMessage converts a transaction into a Message.
-func TransactionToMessage(tx *types.Transaction, s types.Signer, balanceFee, blockNumber, baseFee *big.Int) (*Message, error) {
+func TransactionToMessage(tx *types.Transaction, s types.Signer, balanceFee, blockNumber, baseFee *big.Int, chainConfig *params.ChainConfig) (*Message, error) {
msg := &Message{
Nonce: tx.Nonce(),
GasLimit: tx.Gas(),
@@ -177,9 +178,18 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, balanceFee, blo
if balanceFee != nil {
if blockNumber != nil {
- if blockNumber.Cmp(common.BlockNumberGas50x) >= 0 {
+ if chainConfig == nil {
+ return nil, errors.New("missing chain config for token fee pricing")
+ }
+ if chainConfig.Gas50xBlock == nil {
+ return nil, errors.New("missing Gas50xBlock in chain config for token fee pricing")
+ }
+ if chainConfig.TIPTRC21FeeBlock == nil {
+ return nil, errors.New("missing TIPTRC21FeeBlock in chain config for token fee pricing")
+ }
+ if blockNumber.Cmp(chainConfig.Gas50xBlock) >= 0 {
msg.GasPrice = new(big.Int).Set(common.GasPrice50x)
- } else if blockNumber.Cmp(common.TIPTRC21Fee) > 0 {
+ } else if blockNumber.Cmp(chainConfig.TIPTRC21FeeBlock) > 0 {
msg.GasPrice = new(big.Int).Set(common.TRC21GasPrice)
} else {
msg.GasPrice = new(big.Int).Set(common.TRC21GasPriceBefore)
@@ -497,7 +507,7 @@ func (st *stateTransition) execute(owner common.Address) (*ExecutionResult, erro
// GasPrice of special tx is always 0, so we can skip AddBalance
if !types.IsSpecialTx(msg.To) {
- if st.evm.Context.BlockNumber.Cmp(common.TIPTRC21Fee) > 0 {
+ if st.evm.Context.BlockNumber.Cmp(st.evm.ChainConfig().TIPTRC21FeeBlock) > 0 {
if (owner != common.Address{}) {
st.state.AddBalance(owner, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), msg.GasPrice), tracing.BalanceIncreaseRewardTransactionFee)
}
diff --git a/core/token_validator.go b/core/token_validator.go
index de6289e52f53..dccbc3e88890 100644
--- a/core/token_validator.go
+++ b/core/token_validator.go
@@ -77,7 +77,12 @@ func RunContract(chain consensus.ChainContext, statedb *state.StateDB, contractA
func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext, statedb *state.StateDB) ([]byte, error) {
// Ensure message is initialized properly.
call.GasPrice = big.NewInt(0)
-
+ if call.GasFeeCap == nil {
+ call.GasFeeCap = new(big.Int)
+ }
+ if call.GasTipCap == nil {
+ call.GasTipCap = new(big.Int)
+ }
if call.Gas == 0 {
call.Gas = 1000000
}
@@ -109,7 +114,7 @@ func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext,
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
evmContext := NewEVMBlockContext(chain.CurrentHeader(), chain, nil)
- evm := vm.NewEVM(evmContext, statedb, nil, chain.Config(), vm.Config{})
+ evm := vm.NewEVM(evmContext, statedb, nil, chain.Config(), vm.Config{NoBaseFee: true})
gaspool := new(GasPool).AddGas(1000000)
result, err := ApplyMessage(evm, msg, gaspool, common.Address{})
if err != nil {
diff --git a/core/txpool/errors.go b/core/txpool/errors.go
index 3f4c1161adc8..68d3aeebd8e6 100644
--- a/core/txpool/errors.go
+++ b/core/txpool/errors.go
@@ -84,5 +84,9 @@ var (
// by an account that is not an authorized signer.
ErrSpecialTxNotFromSigner = errors.New("special transaction sender is not a signer")
+ // ErrMissingChainConfig is returned when txpool validation is invoked without
+ // a chain config. This prevents silently skipping fork-gated checks.
+ ErrMissingChainConfig = errors.New("missing chain config")
+
ErrMinDeploySMC = errors.New("smart contract creation cost is under allowance")
)
diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go
index 3ac2ab2132dd..642cd21fb45f 100644
--- a/core/txpool/legacypool/legacypool.go
+++ b/core/txpool/legacypool/legacypool.go
@@ -585,6 +585,8 @@ func (pool *LegacyPool) ValidateTxBasics(tx *types.Transaction) error {
// rules and adheres to some heuristic limits of the local node (price and size).
func (pool *LegacyPool) validateTx(tx *types.Transaction) error {
opts := &txpool.ValidationOptionsWithState{
+ Config: pool.chainconfig,
+
State: pool.currentState,
FirstNonceGap: nil, // Pool allows arbitrary arrival order, don't invalidate nonce gaps
@@ -623,13 +625,13 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error {
}
// Validate minFee slot for XDCZ
- if tx.IsXDCZApplyTransaction() {
+ if tx.IsXDCZApplyTransaction(pool.chain.Config()) {
copyState := opts.State.Copy()
return core.ValidateXDCZApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:]))
}
// Validate balance slot, token decimal for XDCX
- if tx.IsXDCXApplyTransaction() {
+ if tx.IsXDCXApplyTransaction(pool.chain.Config()) {
copyState := opts.State.Copy()
return core.ValidateXDCXApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:]))
}
@@ -1498,7 +1500,7 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T
if head := pool.chain.CurrentHeader(); head != nil {
number = head.Number
}
- promotable, dropped, removedAddresses := pool.queue.promoteExecutables(accounts, gasLimit, pool.currentState, pool.pendingNonces, pool.trc21FeeCapacity, number)
+ promotable, dropped, removedAddresses := pool.queue.promoteExecutables(accounts, gasLimit, pool.currentState, pool.pendingNonces, pool.trc21FeeCapacity, number, pool.chainconfig.Gas50xBlock)
// promote all promotable transactions
promoted := make([]*types.Transaction, 0, len(promotable))
@@ -1650,7 +1652,7 @@ func (pool *LegacyPool) demoteUnexecutables() {
if pool.chain.CurrentHeader() != nil {
number = pool.chain.CurrentHeader().Number
}
- drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit, pool.trc21FeeCapacity, number)
+ drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit, pool.trc21FeeCapacity, number, pool.chainconfig.Gas50xBlock)
for _, tx := range drops {
hash := tx.Hash()
pool.all.Remove(hash)
diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go
index f4afdb1bcdb0..5c68604fb546 100644
--- a/core/txpool/legacypool/legacypool_test.go
+++ b/core/txpool/legacypool/legacypool_test.go
@@ -1571,7 +1571,7 @@ func TestAllowedTxSize(t *testing.T) {
account := crypto.PubkeyToAddress(key.PublicKey)
testAddBalance(pool, account, big.NewInt(1000000000000000000))
- minGasPrice := common.GetMinGasPrice(pool.currentHead.Load().Number)
+ minGasPrice := common.GetMinGasPrice(pool.currentHead.Load().Number, pool.chainconfig.Gas50xBlock)
// Find the maximum data length for the kind of transaction which will
// be generated in the pool.addRemoteSync calls below.
@@ -1815,7 +1815,7 @@ func TestMinGasPriceEnforced(t *testing.T) {
key, _ := crypto.GenerateKey()
testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1_000_000_000_000_000_000))
- minGasPrice := common.GetMinGasPrice(blockchain.CurrentBlock().Number)
+ minGasPrice := common.GetMinGasPrice(blockchain.CurrentBlock().Number, blockchain.Config().Gas50xBlock)
legacyPrice := new(big.Int).Add(minGasPrice, big.NewInt(1))
dynamicTip := new(big.Int).Add(minGasPrice, big.NewInt(1))
dynamicFeeCap := new(big.Int).Add(minGasPrice, big.NewInt(2))
diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go
index e806d9a6ff75..43d07413d68c 100644
--- a/core/txpool/legacypool/list.go
+++ b/core/txpool/legacypool/list.go
@@ -373,7 +373,7 @@ func (l *list) Forward(threshold uint64) types.Transactions {
// 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
// the newly invalidated transactions.
-func (l *list) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[common.Address]*big.Int, number *big.Int) (types.Transactions, types.Transactions) {
+func (l *list) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[common.Address]*big.Int, number, gas50xBlock *big.Int) (types.Transactions, types.Transactions) {
// If all transactions are below the threshold, short circuit
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
return nil, nil
@@ -386,7 +386,7 @@ func (l *list) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[comm
maximum := costLimit
if tx.To() != nil {
if feeCapacity, ok := trc21Issuers[*tx.To()]; ok {
- return tx.Gas() > gasLimit || new(big.Int).Add(costLimit, feeCapacity).Cmp(tx.TxCost(number)) < 0
+ return tx.Gas() > gasLimit || new(big.Int).Add(costLimit, feeCapacity).Cmp(tx.TxCost(number, gas50xBlock)) < 0
}
}
return tx.Gas() > gasLimit || tx.Cost().Cmp(maximum) > 0
diff --git a/core/txpool/legacypool/list_test.go b/core/txpool/legacypool/list_test.go
index 4aca0529c6d1..d9c733c12d9a 100644
--- a/core/txpool/legacypool/list_test.go
+++ b/core/txpool/legacypool/list_test.go
@@ -143,7 +143,7 @@ func BenchmarkListAdd(t *testing.B) {
t.ResetTimer()
for _, v := range rand.Perm(len(txs)) {
list.Add(txs[v], DefaultConfig.PriceBump)
- list.Filter(priceLimit, DefaultConfig.PriceBump, nil, nil)
+ list.Filter(priceLimit, DefaultConfig.PriceBump, nil, nil, nil)
}
}
diff --git a/core/txpool/legacypool/queue.go b/core/txpool/legacypool/queue.go
index a70c175438ce..03e1316e6b0a 100644
--- a/core/txpool/legacypool/queue.go
+++ b/core/txpool/legacypool/queue.go
@@ -160,7 +160,7 @@ func (q *queue) add(tx *types.Transaction) (*common.Hash, error) {
// - all transactions that were removed from the queue and selected for promotion;
// - all other transactions that were removed from the queue and dropped;
// - the list of addresses removed.
-func (q *queue) promoteExecutables(accounts []common.Address, gasLimit uint64, currentState *state.StateDB, nonces *noncer, trc21FeeCapacity map[common.Address]*big.Int, number *big.Int) ([]*types.Transaction, []common.Hash, []common.Address) {
+func (q *queue) promoteExecutables(accounts []common.Address, gasLimit uint64, currentState *state.StateDB, nonces *noncer, trc21FeeCapacity map[common.Address]*big.Int, number, gas50xBlock *big.Int) ([]*types.Transaction, []common.Hash, []common.Address) {
// Track the promotable transactions to broadcast them at once
var (
promotable []*types.Transaction
@@ -181,7 +181,7 @@ func (q *queue) promoteExecutables(accounts []common.Address, gasLimit uint64, c
log.Trace("Removing old queued transactions", "count", len(forwards))
// Drop all transactions that are too costly (low balance or out of gas)
- drops, _ := list.Filter(currentState.GetBalance(addr), gasLimit, trc21FeeCapacity, number)
+ drops, _ := list.Filter(currentState.GetBalance(addr), gasLimit, trc21FeeCapacity, number, gas50xBlock)
for _, tx := range drops {
dropped = append(dropped, tx.Hash())
}
diff --git a/core/txpool/validation.go b/core/txpool/validation.go
index cb214b70c676..9e70a3b5badc 100644
--- a/core/txpool/validation.go
+++ b/core/txpool/validation.go
@@ -153,6 +153,8 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
// ValidationOptionsWithState define certain differences between stateful transaction
// validation across the different pools without having to duplicate those checks.
type ValidationOptionsWithState struct {
+ Config *params.ChainConfig // Chain configuration to selectively validate based on current fork rules
+
State *state.StateDB // State database to check nonces and balances against
// FirstNonceGap is an optional callback to retrieve the first nonce gap in
@@ -187,6 +189,12 @@ type ValidationOptionsWithState struct {
// This check is public to allow different transaction pools to check the stateful
// rules without duplicating code and running the risk of missed updates.
func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, opts *ValidationOptionsWithState) error {
+ if opts.Config == nil {
+ return ErrMissingChainConfig
+ }
+ if opts.State != nil {
+ opts.State.SetChainConfig(opts.Config)
+ }
// Ensure the transaction adheres to nonce ordering
from, err := types.Sender(signer, tx) // already validated (and cached), but cleaner to check
if err != nil {
@@ -222,7 +230,7 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op
if !opts.State.ValidateTRC21Tx(from, *to, tx.Data()) {
return core.ErrInsufficientFunds
}
- cost = tx.TxCost(number)
+ cost = tx.TxCost(number, opts.Config.Gas50xBlock)
}
}
newBalance := new(big.Int).Add(balance, feeCapacity)
@@ -255,7 +263,7 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op
}
// Ensure sender and receiver are not in denylist
- if number == nil || number.Cmp(new(big.Int).SetUint64(common.DenylistHFNumber)) >= 0 {
+ if number == nil || opts.Config.IsDenylist(number) {
// check if sender is in denylist
if common.IsInDenylist(tx.From()) {
return fmt.Errorf("reject transaction with sender in denylist: %v", tx.From().Hex())
@@ -268,7 +276,7 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op
// Validate gas price
if !tx.IsSpecialTransaction() {
- minGasPrice := common.GetMinGasPrice(number)
+ minGasPrice := common.GetMinGasPrice(number, opts.Config.Gas50xBlock)
if tx.GasPrice().Cmp(minGasPrice) < 0 {
return ErrUnderMinGasPrice
}
diff --git a/core/txpool/validation_denylist_test.go b/core/txpool/validation_denylist_test.go
new file mode 100644
index 000000000000..cc02d8abc349
--- /dev/null
+++ b/core/txpool/validation_denylist_test.go
@@ -0,0 +1,106 @@
+package txpool
+
+import (
+ "math/big"
+ "strings"
+ "testing"
+
+ "github.com/XinFinOrg/XDPoSChain/common"
+ "github.com/XinFinOrg/XDPoSChain/core/rawdb"
+ "github.com/XinFinOrg/XDPoSChain/core/state"
+ "github.com/XinFinOrg/XDPoSChain/core/tracing"
+ "github.com/XinFinOrg/XDPoSChain/core/types"
+ "github.com/XinFinOrg/XDPoSChain/crypto"
+ "github.com/XinFinOrg/XDPoSChain/params"
+)
+
+func newValidationStateOpts(t *testing.T, cfg *params.ChainConfig, number *big.Int) (*types.Transaction, types.Signer, *ValidationOptionsWithState) {
+ t.Helper()
+
+ statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()))
+ if err != nil {
+ t.Fatalf("failed to create state: %v", err)
+ }
+
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ t.Fatalf("failed to generate key: %v", err)
+ }
+ from := crypto.PubkeyToAddress(key.PublicKey)
+ statedb.AddBalance(from, new(big.Int).Mul(big.NewInt(1_000_000), big.NewInt(params.Ether)), tracing.BalanceChangeUnspecified)
+
+ denylistedReceiver := common.HexToAddress("0x5248bfb72fd4f234e062d3e9bb76f08643004fcd")
+ gasPrice := new(big.Int).Mul(new(big.Int).Set(common.MinGasPrice), big.NewInt(10))
+ tx, err := types.SignTx(
+ types.NewTransaction(0, denylistedReceiver, big.NewInt(1), params.TxGas, gasPrice, nil),
+ types.HomesteadSigner{},
+ key,
+ )
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+
+ opts := &ValidationOptionsWithState{
+ Config: cfg,
+ State: statedb,
+ ExistingExpenditure: func(common.Address) *big.Int {
+ return new(big.Int)
+ },
+ ExistingCost: func(common.Address, uint64) *big.Int {
+ return nil
+ },
+ PendingNonce: func(common.Address) uint64 {
+ return 0
+ },
+ CurrentNumber: func() *big.Int {
+ return number
+ },
+ }
+
+ return tx, types.HomesteadSigner{}, opts
+}
+
+func TestValidateTransactionWithStateDenylistHardForkBoundaries(t *testing.T) {
+ cfg := ¶ms.ChainConfig{DenylistBlock: big.NewInt(100), Gas50xBlock: big.NewInt(1000)}
+
+ t.Run("missing chain config returns explicit error", func(t *testing.T) {
+ tx, signer, opts := newValidationStateOpts(t, nil, big.NewInt(100))
+ opts.Config = nil
+ err := ValidateTransactionWithState(tx, signer, opts)
+ if err == nil {
+ t.Fatal("expected missing chain config error")
+ }
+ if err != ErrMissingChainConfig {
+ t.Fatalf("unexpected error: have %v want %v", err, ErrMissingChainConfig)
+ }
+ })
+
+ t.Run("below hard fork allows denylisted receiver", func(t *testing.T) {
+ tx, signer, opts := newValidationStateOpts(t, cfg, big.NewInt(99))
+ if err := ValidateTransactionWithState(tx, signer, opts); err != nil {
+ t.Fatalf("unexpected error below hard fork: %v", err)
+ }
+ })
+
+ t.Run("at hard fork rejects denylisted receiver", func(t *testing.T) {
+ tx, signer, opts := newValidationStateOpts(t, cfg, big.NewInt(100))
+ err := ValidateTransactionWithState(tx, signer, opts)
+ if err == nil {
+ t.Fatal("expected denylist error at hard fork")
+ }
+ if !strings.Contains(err.Error(), "receiver in denylist") {
+ t.Fatalf("unexpected error at hard fork: %v", err)
+ }
+ })
+
+ t.Run("above hard fork rejects denylisted receiver", func(t *testing.T) {
+ tx, signer, opts := newValidationStateOpts(t, cfg, big.NewInt(101))
+ err := ValidateTransactionWithState(tx, signer, opts)
+ if err == nil {
+ t.Fatal("expected denylist error above hard fork")
+ }
+ if !strings.Contains(err.Error(), "receiver in denylist") {
+ t.Fatalf("unexpected error above hard fork: %v", err)
+ }
+ })
+}
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 2112317aacb9..d417d3673225 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -28,6 +28,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/crypto"
+ "github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/holiman/uint256"
)
@@ -538,8 +539,8 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
}
// TxCost returns gas * gasPrice + value.
-func (tx *Transaction) TxCost(number *big.Int) *big.Int {
- total := new(big.Int).Mul(common.GetGasPrice(number), new(big.Int).SetUint64(tx.Gas()))
+func (tx *Transaction) TxCost(number, gas50xBlock *big.Int) *big.Int {
+ total := new(big.Int).Mul(common.GetGasPrice(number, gas50xBlock), new(big.Int).SetUint64(tx.Gas()))
total.Add(total, tx.Value())
return total
}
@@ -653,9 +654,9 @@ func (tx *Transaction) IsVotingTransaction() (bool, *common.Address) {
return true, &m
}
-func (tx *Transaction) IsXDCXApplyTransaction() bool {
+func (tx *Transaction) IsXDCXApplyTransaction(config *params.ChainConfig) bool {
to := tx.To()
- if to == nil || *to != common.XDCXListingSMC {
+ if config == nil || to == nil || *to != config.XDCXListingSMC {
return false
}
data := tx.Data()
@@ -668,9 +669,9 @@ func (tx *Transaction) IsXDCXApplyTransaction() bool {
return method == common.XDCXApplyMethod
}
-func (tx *Transaction) IsXDCZApplyTransaction() bool {
+func (tx *Transaction) IsXDCZApplyTransaction(config *params.ChainConfig) bool {
to := tx.To()
- if to == nil || *to != common.TRC21IssuerSMC {
+ if config == nil || to == nil || *to != config.TRC21IssuerSMC {
return false
}
data := tx.Data()
diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go
index 1024e5cd5e8c..91d97a91da4a 100644
--- a/core/types/transaction_signing.go
+++ b/core/types/transaction_signing.go
@@ -20,7 +20,6 @@ import (
"crypto/ecdsa"
"errors"
"fmt"
- "math"
"math/big"
"github.com/XinFinOrg/XDPoSChain/common"
@@ -40,6 +39,9 @@ type sigCache struct {
// MakeSigner returns a Signer based on the given chain config and block number.
func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
+ if config == nil {
+ return HomesteadSigner{}
+ }
var signer Signer
switch {
case config.IsPrague(blockNumber):
@@ -65,17 +67,19 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
// have the current block number available, use MakeSigner instead.
func LatestSigner(config *params.ChainConfig) Signer {
var signer Signer
- if config.ChainID != nil {
+ if config != nil && config.ChainID != nil {
switch {
- case common.PragueBlock.Int64() != math.MaxInt64 || config.PragueBlock != nil:
+ case config.PragueBlock != nil:
signer = NewPragueSigner(config.ChainID)
- case common.Eip1559Block.Int64() != math.MaxInt64 || config.Eip1559Block != nil:
+ case config.Eip1559Block != nil:
signer = NewLondonSigner(config.ChainID)
case config.EIP155Block != nil:
signer = NewEIP155Signer(config.ChainID)
default:
signer = HomesteadSigner{}
}
+ } else {
+ signer = HomesteadSigner{}
}
return signer
}
diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go
index 6dffdb560537..2cbf81fc090f 100644
--- a/core/types/transaction_test.go
+++ b/core/types/transaction_test.go
@@ -519,6 +519,27 @@ func BenchmarkEffectiveGasTipCmp(b *testing.B) {
})
}
+func TestLatestSignerUsesModernSignerForXDPoSMockChainConfig(t *testing.T) {
+ signer := LatestSigner(params.TestXDPoSMockChainConfig)
+ if _, ok := signer.(pragueSigner); !ok {
+ t.Fatalf("unexpected signer type %T, want pragueSigner for TestXDPoSMockChainConfig", signer)
+ }
+}
+
+func TestLatestSignerNilConfigReturnsHomesteadSigner(t *testing.T) {
+ signer := LatestSigner(nil)
+ if _, ok := signer.(HomesteadSigner); !ok {
+ t.Fatalf("unexpected signer type %T, want HomesteadSigner for nil config", signer)
+ }
+}
+
+func TestMakeSignerNilConfigReturnsHomesteadSigner(t *testing.T) {
+ signer := MakeSigner(nil, big.NewInt(0))
+ if _, ok := signer.(HomesteadSigner); !ok {
+ t.Fatalf("unexpected signer type %T, want HomesteadSigner for nil config", signer)
+ }
+}
+
func TestEffectiveGasTipIntCmpMatchesBigIntSemantics(t *testing.T) {
tests := []struct {
name string
diff --git a/core/vm/XDCx_price.go b/core/vm/XDCx_price.go
index c5ffd8119151..54516bfd7eb3 100644
--- a/core/vm/XDCx_price.go
+++ b/core/vm/XDCx_price.go
@@ -10,13 +10,9 @@ import (
const XDCXPriceNumberOfBytesReturn = 32
// XDCxPrice implements a pre-compile contract to get token price in XDCx
-
type XDCxLastPrice struct {
tradingStateDB *tradingstate.TradingStateDB
}
-type XDCxEpochPrice struct {
- tradingStateDB *tradingstate.TradingStateDB
-}
func (t *XDCxLastPrice) RequiredGas(input []byte) uint64 {
return params.XDCXPriceGas
@@ -44,6 +40,14 @@ func (t *XDCxLastPrice) SetTradingState(tradingStateDB *tradingstate.TradingStat
}
}
+func (c *XDCxLastPrice) Name() string {
+ return "XDCX_LAST_PRICE"
+}
+
+type XDCxEpochPrice struct {
+ tradingStateDB *tradingstate.TradingStateDB
+}
+
func (t *XDCxEpochPrice) RequiredGas(input []byte) uint64 {
return params.XDCXPriceGas
}
@@ -69,3 +73,7 @@ func (t *XDCxEpochPrice) SetTradingState(tradingStateDB *tradingstate.TradingSta
t.tradingStateDB = nil
}
}
+
+func (c *XDCxEpochPrice) Name() string {
+ return "XDCX_EPOCH_PRICE"
+}
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index ebfaa24b1650..41a9cad2bae4 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -40,6 +40,7 @@ import (
type PrecompiledContract interface {
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
Run(input []byte) ([]byte, error) // Run runs the precompiled contract
+ Name() string
}
// PrecompiledContracts contains the precompiled contracts supported at the given fork.
@@ -268,6 +269,10 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) {
return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
}
+func (c *ecrecover) Name() string {
+ return "ECREC"
+}
+
// SHA256 implemented as a native contract.
type sha256hash struct{}
@@ -283,6 +288,10 @@ func (c *sha256hash) Run(input []byte) ([]byte, error) {
return h[:], nil
}
+func (c *sha256hash) Name() string {
+ return "SHA256"
+}
+
// RIPEMD160 implemented as a native contract.
type ripemd160hash struct{}
@@ -299,6 +308,10 @@ func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
}
+func (c *ripemd160hash) Name() string {
+ return "RIPEMD160"
+}
+
// data copy implemented as a native contract.
type dataCopy struct{}
@@ -313,6 +326,10 @@ func (c *dataCopy) Run(in []byte) ([]byte, error) {
return common.CopyBytes(in), nil
}
+func (c *dataCopy) Name() string {
+ return "ID"
+}
+
// bigModExp implements a native big integer exponential modular operation.
type bigModExp struct {
eip2565 bool
@@ -503,6 +520,10 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
return common.LeftPadBytes(v, int(modLen)), nil
}
+func (c *bigModExp) Name() string {
+ return "MODEXP"
+}
+
// newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,
// returning it, or an error if the point is invalid.
func newCurvePoint(blob []byte) (*bn256.G1, error) {
@@ -552,6 +573,10 @@ func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
return runBn256Add(input)
}
+func (c *bn256AddIstanbul) Name() string {
+ return "BN254_ADD"
+}
+
// bn256AddByzantium implements a native elliptic curve point addition
// conforming to Byzantium consensus rules.
type bn256AddByzantium struct{}
@@ -565,6 +590,10 @@ func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) {
return runBn256Add(input)
}
+func (c *bn256AddByzantium) Name() string {
+ return "BN254_ADD"
+}
+
// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by
// both Byzantium and Istanbul operations.
func runBn256ScalarMul(input []byte) ([]byte, error) {
@@ -590,6 +619,10 @@ func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
return runBn256ScalarMul(input)
}
+func (c *bn256ScalarMulIstanbul) Name() string {
+ return "BN254_MUL"
+}
+
// bn256ScalarMulByzantium implements a native elliptic curve scalar
// multiplication conforming to Byzantium consensus rules.
type bn256ScalarMulByzantium struct{}
@@ -603,6 +636,10 @@ func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) {
return runBn256ScalarMul(input)
}
+func (c *bn256ScalarMulByzantium) Name() string {
+ return "BN254_MUL"
+}
+
var (
// true32Byte is returned if the bn256 pairing check succeeds.
true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
@@ -646,15 +683,9 @@ func runBn256Pairing(input []byte) ([]byte, error) {
}
type ringSignatureVerifier struct{}
-type bulletproofVerifier struct{}
-
-func (c *bulletproofVerifier) RequiredGas(input []byte) uint64 {
- //the gas should depends on the ringsize
- return 100000
-}
func (c *ringSignatureVerifier) RequiredGas(input []byte) uint64 {
- //the gas should depends on the ringsize
+ // Ring signature verification currently uses a fixed gas charge.
return 100000
}
@@ -669,6 +700,21 @@ func (c *ringSignatureVerifier) Run(proof []byte) ([]byte, error) {
return []byte{}, nil
}
+func (c *ringSignatureVerifier) Name() string {
+ return "RING_SIG_VERIFY"
+}
+
+type bulletproofVerifier struct{}
+
+func (c *bulletproofVerifier) RequiredGas(input []byte) uint64 {
+ // Bulletproof verification currently uses a fixed gas charge.
+ return 100000
+}
+
+func (c *bulletproofVerifier) Name() string {
+ return "BULLET_PROOF_VERIFY"
+}
+
func (c *bulletproofVerifier) Run(proof []byte) ([]byte, error) {
mrp := new(privacy.MultiRangeProof)
if mrp.Deserialize(proof) != nil {
@@ -694,6 +740,10 @@ func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
return runBn256Pairing(input)
}
+func (c *bn256PairingIstanbul) Name() string {
+ return "BN254_PAIRING"
+}
+
// bn256PairingByzantium implements a pairing pre-compile for the bn256 curve
// conforming to Byzantium consensus rules.
type bn256PairingByzantium struct{}
@@ -707,6 +757,10 @@ func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) {
return runBn256Pairing(input)
}
+func (c *bn256PairingByzantium) Name() string {
+ return "BN254_PAIRING"
+}
+
type blake2F struct{}
func (c *blake2F) RequiredGas(input []byte) uint64 {
@@ -718,6 +772,10 @@ func (c *blake2F) RequiredGas(input []byte) uint64 {
return uint64(binary.BigEndian.Uint32(input[0:4]))
}
+func (c *blake2F) Name() string {
+ return "BLAKE2F"
+}
+
const (
blake2FInputLength = 213
blake2FFinalBlockBytes = byte(1)
diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go
index 26092676a0d0..11107470313c 100644
--- a/core/vm/gas_table_test.go
+++ b/core/vm/gas_table_test.go
@@ -199,7 +199,12 @@ func TestCreateGas(t *testing.T) {
BlockNumber: big.NewInt(0),
}
config := Config{}
- chainConfig := params.AllEthashProtocolChanges
+ legacyConfig := *params.AllEthashProtocolChanges
+ legacyConfig.Eip1559Block = nil
+ legacyConfig.CancunBlock = nil
+ legacyConfig.PragueBlock = nil
+ legacyConfig.OsakaBlock = nil
+ chainConfig := &legacyConfig
if tt.eip3860 {
config.ExtraEips = []int{3860}
chainConfig = params.MergedTestChainConfig
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index 9105df844ab5..63ca9bb139d3 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -55,22 +55,23 @@ type Config struct {
func setDefaults(cfg *Config) {
if cfg.ChainConfig == nil {
cfg.ChainConfig = ¶ms.ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: new(big.Int),
- DAOForkBlock: new(big.Int),
- DAOForkSupport: false,
- EIP150Block: new(big.Int),
- EIP155Block: new(big.Int),
- EIP158Block: new(big.Int),
- ByzantiumBlock: new(big.Int),
- ConstantinopleBlock: new(big.Int),
- PetersburgBlock: new(big.Int),
- IstanbulBlock: new(big.Int),
- BerlinBlock: new(big.Int),
- LondonBlock: new(big.Int),
- MergeBlock: new(big.Int),
- ShanghaiBlock: new(big.Int),
- Eip1559Block: new(big.Int),
+ ChainID: big.NewInt(1),
+ HomesteadBlock: new(big.Int),
+ DAOForkBlock: new(big.Int),
+ DAOForkSupport: false,
+ EIP150Block: new(big.Int),
+ EIP155Block: new(big.Int),
+ EIP158Block: new(big.Int),
+ ByzantiumBlock: new(big.Int),
+ ConstantinopleBlock: new(big.Int),
+ PetersburgBlock: new(big.Int),
+ IstanbulBlock: new(big.Int),
+ TIPXDCXCancellationFeeBlock: new(big.Int),
+ BerlinBlock: new(big.Int),
+ LondonBlock: new(big.Int),
+ MergeBlock: new(big.Int),
+ ShanghaiBlock: new(big.Int),
+ Eip1559Block: new(big.Int),
}
}
diff --git a/docs/xdc/XDPoS/XDPoS.md b/docs/xdc/XDPoS/XDPoS.md
index c6367df335b0..19655f6f3f70 100644
--- a/docs/xdc/XDPoS/XDPoS.md
+++ b/docs/xdc/XDPoS/XDPoS.md
@@ -1,6 +1,111 @@
-
# Module XDPoS
+## Method XDPoS_getConfig
+
+The `getConfig` method returns the chain configuration metadata for the current fork boundary, the next scheduled fork boundary, and the last known future fork boundary.
+
+This method is an XDPoS-specific extension. It is inspired by `eth_config` / EIP-7910, but it does not strictly match geth.
+
+Compatibility notes:
+
+- XDPoS returns `activationBlock` for each config entry.
+- geth uses `activationTime` for time-based fork scheduling.
+- XDPoS currently selects `current`, `next`, and `last` using block-based fork activation metadata.
+- XDPoS may include chain-specific precompiles and system contracts that do not exist on Ethereum mainnet.
+
+Parameters:
+
+None
+
+Returns:
+
+result: object configResponse
+
+- current: object config, the currently active fork boundary.
+- next: object config, the next scheduled fork boundary, or `null` if no future fork is known.
+- last: object config, the last known future fork boundary, or `null` if no future fork is known.
+
+Config object fields:
+
+- activationBlock: uint64, the block height at which this configuration becomes active.
+- chainId: big.Int, the configured chain ID represented as a hexadecimal string.
+- forkId: hex-encoded bytes string, the fork identifier derived from the configured fork schedule (for example, `"0x4f9a9c51"`).
+- activeForks: array of string, the modeled forks active at this `activationBlock`. Values use the RPC's fork labels as returned by `forks.Fork.String()` (for example, `"EIP1559"`, `"Prague"`, `"Cancun"`).
+- precompiles: object, a map of active precompile names to contract addresses.
+- systemContracts: object, a map of active system contract names to contract addresses.
+
+Example:
+
+```shell
+curl -s -X POST -H "Content-Type: application/json" ${RPC} -d '{
+ "jsonrpc": "2.0",
+ "id": 1001,
+ "method": "XDPoS_getConfig"
+}' | jq
+```
+
+Response:
+
+The example below is illustrative. Actual fork IDs, precompiles, and system contracts depend on the chain configuration active on the node.
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 1001,
+ "result": {
+ "current": {
+ "activationBlock": 1000,
+ "chainId": "0x32",
+ "forkId": "0x4f9a9c51",
+ "activeForks": [
+ "EIP1559",
+ "Prague"
+ ],
+ "precompiles": {
+ "ECREC": "0x0000000000000000000000000000000000000001",
+ "SHA256": "0x0000000000000000000000000000000000000002",
+ "BLAKE2F": "0x0000000000000000000000000000000000000009"
+ },
+ "systemContracts": {
+ "HISTORY_STORAGE_ADDRESS": "0x0000F90827F1C53a10cb7A02335B175320002935"
+ }
+ },
+ "next": {
+ "activationBlock": 2000,
+ "chainId": "0x32",
+ "forkId": "0xd0c4b3b7",
+ "activeForks": [
+ "Cancun"
+ ],
+ "precompiles": {
+ "ECREC": "0x0000000000000000000000000000000000000001",
+ "SHA256": "0x0000000000000000000000000000000000000002",
+ "BLAKE2F": "0x0000000000000000000000000000000000000009"
+ },
+ "systemContracts": {
+ "HISTORY_STORAGE_ADDRESS": "0x0000F90827F1C53a10cb7A02335B175320002935"
+ }
+ },
+ "last": {
+ "activationBlock": 3000,
+ "chainId": "0x32",
+ "forkId": "0x6b495dfd",
+ "activeForks": [
+ "Osaka"
+ ],
+ "precompiles": {
+ "ECREC": "0x0000000000000000000000000000000000000001",
+ "SHA256": "0x0000000000000000000000000000000000000002",
+ "BLAKE2F": "0x0000000000000000000000000000000000000009"
+ },
+ "systemContracts": {
+ "HISTORY_STORAGE_ADDRESS": "0x0000F90827F1C53a10cb7A02335B175320002935"
+ }
+ }
+ }
+}
+```
+
## Method XDPoS_getBlockInfoByEpochNum
Parameters:
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 3493dfc54812..98b288d90e73 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -557,7 +557,7 @@ func (b *EthAPIBackend) GetVotersRewards(masternodeAddr common.Address) map[comm
var voterResults map[common.Address]*big.Int
for signer, calcReward := range rewardSigners {
if signer == masternodeAddr {
- rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, state, masternodeAddr, calcReward, number)
+ rewards, err := contracts.CalculateRewardForHolders(chain.Config(), foundationWalletAddr, state, masternodeAddr, calcReward, header.Number)
if err != nil {
log.Error("Fail to calculate reward for holders.", "error", err)
return nil
diff --git a/eth/backend.go b/eth/backend.go
index acac40a8efc3..ffefcafd3d67 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -131,9 +131,12 @@ func New(stack *node.Node, config *ethconfig.Config, XDCXServ *XDCx.XDCX, lendin
}
// Resolve the effective chain config (and persist it when compatible)
// before constructing the consensus engine so it initializes with final network settings.
- chainConfig, _, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis)
- if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
- return nil, genesisErr
+ chainConfig, _, _, err := core.SetupGenesisBlock(chainDb, config.Genesis)
+ if chainConfig == nil {
+ return nil, fmt.Errorf("nil chain config returned from SetupGenesisBlock (err=%v)", err)
+ }
+ if err != nil {
+ return nil, err
}
// Set networkID to chainID by default.
@@ -141,7 +144,6 @@ func New(stack *node.Node, config *ethconfig.Config, XDCXServ *XDCx.XDCX, lendin
if networkID == 0 {
networkID = chainConfig.ChainID.Uint64()
}
- common.CopyConstants(networkID)
engine := CreateConsensusEngine(stack, chainConfig, chainDb)
// Assemble the Ethereum object.
diff --git a/eth/backend_test.go b/eth/backend_test.go
index f30e23c09338..691c19ff2818 100644
--- a/eth/backend_test.go
+++ b/eth/backend_test.go
@@ -4,8 +4,10 @@ import (
"math/big"
"testing"
+ "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
+ "github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/eth/util"
"github.com/XinFinOrg/XDPoSChain/params"
)
@@ -30,7 +32,32 @@ func TestRewardInflation(t *testing.T) {
}
}
-func TestSetupGenesisBlockRepairsMissingV2Config(t *testing.T) {
+func TestRewardInflationUsesChainConfigTIPNoHalvingMNReward(t *testing.T) {
+ chainReward := new(big.Int).Mul(new(big.Int).SetUint64(250), new(big.Int).SetUint64(params.Ether))
+ config := ¶ms.ChainConfig{TIPNoHalvingMNRewardBlock: big.NewInt(20)}
+ reward := util.RewardInflation(testChainReader{cfg: config}, chainReward, 20, 10)
+ if reward.Cmp(new(big.Int).Mul(new(big.Int).SetUint64(250), new(big.Int).SetUint64(params.Ether))) != 0 {
+ t.Fatalf("unexpected reward with no-halving fork: have %v", reward)
+ }
+}
+
+type testChainReader struct {
+ cfg *params.ChainConfig
+}
+
+func (t testChainReader) Config() *params.ChainConfig { return t.cfg }
+
+func (testChainReader) CurrentHeader() *types.Header { return nil }
+
+func (testChainReader) GetHeader(common.Hash, uint64) *types.Header { return nil }
+
+func (testChainReader) GetHeaderByNumber(uint64) *types.Header { return nil }
+
+func (testChainReader) GetHeaderByHash(common.Hash) *types.Header { return nil }
+
+func (testChainReader) GetBlock(common.Hash, uint64) *types.Block { return nil }
+
+func TestSetupGenesisBlockResolvesMissingV2ConfigInMemory(t *testing.T) {
db := rawdb.NewMemoryDatabase()
legacyGenesis := legacyTestnetGenesisWithoutV2()
@@ -43,11 +70,19 @@ func TestSetupGenesisBlockRepairsMissingV2Config(t *testing.T) {
if loadedCfg.XDPoS == nil {
t.Fatal("expected XDPoS config in loaded chain config")
}
- if loadedCfg.XDPoS.V2 != nil {
- t.Fatal("expected stored legacy chain config to have nil XDPoS.V2 before setup")
+
+ persistedBefore, err := rawdb.ReadChainConfig(db, params.TestnetGenesisHash)
+ if err != nil {
+ t.Fatalf("failed to read persisted chain config: %v", err)
+ }
+ if persistedBefore == nil || persistedBefore.XDPoS == nil {
+ t.Fatalf("expected persisted legacy chain config, have %v", persistedBefore)
+ }
+ if persistedBefore.XDPoS.V2 != nil {
+ t.Fatal("expected persisted legacy chain config to keep nil XDPoS.V2 before setup")
}
- finalCfg, _, err := core.SetupGenesisBlock(db, core.DefaultTestnetGenesisBlock())
+ finalCfg, _, _, err := core.SetupGenesisBlock(db, core.DefaultTestnetGenesisBlock())
if err != nil {
t.Fatalf("SetupGenesisBlock failed: %v", err)
}
@@ -57,17 +92,28 @@ func TestSetupGenesisBlockRepairsMissingV2Config(t *testing.T) {
if finalCfg.XDPoS.V2.SwitchBlock.Cmp(params.TestnetChainConfig.XDPoS.V2.SwitchBlock) != 0 {
t.Fatalf("unexpected switch block after setup: have %v want %v", finalCfg.XDPoS.V2.SwitchBlock, params.TestnetChainConfig.XDPoS.V2.SwitchBlock)
}
+
+ persistedAfter, err := rawdb.ReadChainConfig(db, params.TestnetGenesisHash)
+ if err != nil {
+ t.Fatalf("failed to read persisted chain config after setup: %v", err)
+ }
+ if persistedAfter == nil || persistedAfter.XDPoS == nil {
+ t.Fatalf("expected persisted chain config with XDPoS, have %v", persistedAfter)
+ }
+ if persistedAfter.XDPoS.V2 == nil {
+ t.Fatal("expected SetupGenesisBlock to persist in-memory V2 repair")
+ }
}
func TestSetupGenesisBlockIsIdempotentForTestnet(t *testing.T) {
db := rawdb.NewMemoryDatabase()
genesis := core.DefaultTestnetGenesisBlock()
- cfg1, hash1, err := core.SetupGenesisBlock(db, genesis)
+ cfg1, hash1, _, err := core.SetupGenesisBlock(db, genesis)
if err != nil {
t.Fatalf("first SetupGenesisBlock failed: %v", err)
}
- cfg2, hash2, err := core.SetupGenesisBlock(db, genesis)
+ cfg2, hash2, _, err := core.SetupGenesisBlock(db, genesis)
if err != nil {
t.Fatalf("second SetupGenesisBlock failed: %v", err)
}
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index c2ca9171517b..409116464213 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -344,7 +344,7 @@ func (dl *downloadTester) handleProposedBlock(header *types.Header) error {
// Config retrieves the blockchain's chain configuration.
func (dl *downloadTester) Config() *params.ChainConfig {
- config := *params.TestChainConfig
+ config := *testChainConfig
return &config
}
diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go
index 0125ef566cee..e3c3dee4fe88 100644
--- a/eth/downloader/testchain_test.go
+++ b/eth/downloader/testchain_test.go
@@ -33,14 +33,21 @@ import (
// Test chain parameters.
var (
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
- testDB = rawdb.NewMemoryDatabase()
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
+ testDB = rawdb.NewMemoryDatabase()
+ testChainConfig = func() *params.ChainConfig {
+ cfg := *params.TestChainConfig
+ cfg.CancunBlock = nil
+ cfg.PragueBlock = nil
+ cfg.OsakaBlock = nil
+ return &cfg
+ }()
testGspec = &core.Genesis{
Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
- Config: params.TestChainConfig,
+ Config: testChainConfig,
}
testGenesis = testGspec.MustCommit(testDB)
)
@@ -138,7 +145,7 @@ func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool)
}
// Include transactions to the miner to make blocks more interesting.
if parent == tc.genesis && i%22 == 0 {
- signer := types.MakeSigner(params.TestChainConfig, block.Number())
+ signer := types.MakeSigner(testChainConfig, block.Number())
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey)
if err != nil {
panic(err)
diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go
index e7ae052dc736..b6b1768daa21 100644
--- a/eth/filters/filter_test.go
+++ b/eth/filters/filter_test.go
@@ -99,7 +99,9 @@ func BenchmarkFilters(b *testing.B) {
func TestFilters(t *testing.T) {
config := *params.TestChainConfig
- config.Eip1559Block = big.NewInt(0)
+ config.CancunBlock = nil
+ config.PragueBlock = nil
+ config.OsakaBlock = nil
var (
db = rawdb.NewMemoryDatabase()
diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go
index 3ecca17dafe6..7b6140ed92cd 100644
--- a/eth/gasprice/gasprice.go
+++ b/eth/gasprice/gasprice.go
@@ -226,7 +226,7 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) {
// Check min gas price for non-eip1559 block
if head.BaseFee == nil {
- minGasPrice := common.GetMinGasPrice(head.Number)
+ minGasPrice := common.GetMinGasPrice(head.Number, oracle.backend.ChainConfig().Gas50xBlock)
if price.Cmp(minGasPrice) < 0 {
price = new(big.Int).Set(minGasPrice)
}
diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go
index 8942f473bf7d..bf0b5dba63f2 100644
--- a/eth/gasprice/gasprice_test.go
+++ b/eth/gasprice/gasprice_test.go
@@ -25,7 +25,6 @@ import (
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
"github.com/XinFinOrg/XDPoSChain/core"
- "github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm"
"github.com/XinFinOrg/XDPoSChain/crypto"
@@ -109,6 +108,9 @@ func (b *testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) eve
func newTestBackend(t *testing.T, eip1559Block *big.Int, pending bool) *testBackend {
config := *params.TestChainConfig // needs copy because it is modified below
+ if eip1559Block == nil {
+ eip1559Block = big.NewInt(1_000_000_000)
+ }
config.Eip1559Block = eip1559Block
var (
@@ -123,11 +125,11 @@ func newTestBackend(t *testing.T, eip1559Block *big.Int, pending bool) *testBack
engine := ethash.NewFaker()
// Generate testing blocks
- _, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, testHead+1, func(i int, b *core.BlockGen) {
+ db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, testHead+1, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{1})
var txdata types.TxData
- if eip1559Block != nil && b.Number().Cmp(eip1559Block) >= 0 {
+ if b.Number().Cmp(config.Eip1559Block) >= 0 {
txdata = &types.DynamicFeeTx{
ChainID: gspec.Config.ChainID,
Nonce: b.TxNonce(addr),
@@ -150,11 +152,13 @@ func newTestBackend(t *testing.T, eip1559Block *big.Int, pending bool) *testBack
b.AddTx(types.MustSignNewTx(key, signer, txdata))
})
// Construct testing chain
- chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, engine, vm.Config{})
+ chain, err := core.NewBlockChain(db, nil, gspec, engine, vm.Config{})
if err != nil {
t.Fatalf("Failed to create local chain, %v", err)
}
- chain.InsertChain(blocks)
+ if _, err := chain.InsertChain(blocks); err != nil {
+ t.Fatalf("Failed to insert generated chain, %v", err)
+ }
return &testBackend{chain: chain, pending: pending}
}
diff --git a/eth/handler_test.go b/eth/handler_test.go
index 07437a1cda87..8e5c58669dad 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -482,8 +482,10 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
db = rawdb.NewMemoryDatabase()
gspec = &core.Genesis{
Config: ¶ms.ChainConfig{
- DAOForkBlock: big.NewInt(1),
- DAOForkSupport: localForked,
+ ChainID: big.NewInt(1337),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ DAOForkBlock: big.NewInt(1),
+ DAOForkSupport: localForked,
},
}
blockchain, _ = core.NewBlockChain(db, nil, gspec, pow, vm.Config{})
diff --git a/eth/hooks/engine_v1_hooks.go b/eth/hooks/engine_v1_hooks.go
index d089b147dca3..7942518762f8 100644
--- a/eth/hooks/engine_v1_hooks.go
+++ b/eth/hooks/engine_v1_hooks.go
@@ -288,7 +288,7 @@ func AttachConsensusV1Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
voterResults := make(map[common.Address]interface{})
if len(signers) > 0 {
for signer, calcReward := range rewardSigners {
- rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
+ rewards, err := contracts.CalculateRewardForHolders(chain.Config(), foundationWalletAddr, parentState, signer, calcReward, header.Number)
if err != nil {
log.Crit("Fail to calculate reward for holders.", "error", err)
}
diff --git a/eth/hooks/engine_v2_hooks.go b/eth/hooks/engine_v2_hooks.go
index 194ba818b2fa..2df6ecde32ec 100644
--- a/eth/hooks/engine_v2_hooks.go
+++ b/eth/hooks/engine_v2_hooks.go
@@ -312,7 +312,7 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
// Add reward for coin holders.
rewardResults := make(map[common.Address]interface{})
for signer, calcReward := range rewardSigners {
- rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
+ rewards, err := contracts.CalculateRewardForHolders(chain.Config(), foundationWalletAddr, parentState, signer, calcReward, header.Number)
if err != nil {
log.Error("[HookReward] Fail to calculate reward for holders.", "error", err)
return nil, err
@@ -350,7 +350,7 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
// Add reward for coin holders.
rewardResults := make(map[common.Address]interface{})
for signer, calcReward := range rewardSigners {
- rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
+ rewards, err := contracts.CalculateRewardForHolders(chain.Config(), foundationWalletAddr, parentState, signer, calcReward, header.Number)
if err != nil {
log.Error("[HookReward] Fail to calculate reward for holders.", "error", err)
return nil, err
diff --git a/eth/state_accessor.go b/eth/state_accessor.go
index ecdf0d83e480..650df48a502f 100644
--- a/eth/state_accessor.go
+++ b/eth/state_accessor.go
@@ -229,7 +229,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
}
}
// Assemble the transaction call message and return if the requested offset
- msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee())
+ msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee(), eth.blockchain.Config())
// Not yet the searched for transaction, execute on top of the current state
statedb.SetTxContext(tx.Hash(), idx)
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index 94cc8bfeba50..4eba59f8f9d1 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -275,7 +275,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
}
}
header := task.block.Header()
- msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee)
+ msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee, api.backend.ChainConfig())
txctx := &Context{
BlockHash: task.block.Hash(),
BlockNumber: task.block.Number(),
@@ -539,7 +539,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
balance = value
}
}
- msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee())
+ msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee(), api.backend.ChainConfig())
statedb.SetTxContext(tx.Hash(), i)
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{}); err != nil {
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
@@ -617,7 +617,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
}
}
// Generate the next state snapshot fast without tracing
- msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee())
+ msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee(), api.backend.ChainConfig())
txctx := &Context{
BlockHash: blockHash,
BlockNumber: block.Number(),
@@ -667,7 +667,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
}
}
header := block.Header()
- msg, _ := core.TransactionToMessage(txs[task.index], signer, balance, header.Number, header.BaseFee)
+ msg, _ := core.TransactionToMessage(txs[task.index], signer, balance, header.Number, header.BaseFee, api.backend.ChainConfig())
txctx := &Context{
BlockHash: blockHash,
BlockNumber: block.Number(),
@@ -718,7 +718,7 @@ txloop:
}
// Generate the next state snapshot fast without tracing
header := block.Header()
- msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee)
+ msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee, api.backend.ChainConfig())
statedb.SetTxContext(tx.Hash(), i)
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{}); err != nil {
failed = err
@@ -774,7 +774,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
balance = value
}
}
- msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number()), balance, block.Number(), block.BaseFee())
+ msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number()), balance, block.Number(), block.BaseFee(), api.backend.ChainConfig())
if err != nil {
return nil, err
}
diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go
index cb237b84dc01..ea675f882427 100644
--- a/eth/tracers/api_test.go
+++ b/eth/tracers/api_test.go
@@ -182,7 +182,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
if idx == txIndex {
return tx, context, statedb, release, nil
}
- msg, _ := core.TransactionToMessage(tx, signer, nil, block.Number(), block.BaseFee())
+ msg, _ := core.TransactionToMessage(tx, signer, nil, block.Number(), block.BaseFee(), b.chainConfig)
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{}); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
}
@@ -251,7 +251,6 @@ func TestStateHooks(t *testing.T) {
signer = types.HomesteadSigner{}
nonce = uint64(0)
)
- config.Eip1559Block = big.NewInt(0)
backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
@@ -302,7 +301,6 @@ func TestTraceCall(t *testing.T) {
// Initialize test accounts
config := *params.TestChainConfig
- config.Eip1559Block = big.NewInt(0)
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: &config,
@@ -662,7 +660,6 @@ func TestTracingWithOverrides(t *testing.T) {
// Initialize test accounts
config := *params.TestChainConfig
- config.Eip1559Block = big.NewInt(0)
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: &config,
diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go
index a68cf37198aa..6e8e17e032ec 100644
--- a/eth/tracers/internal/tracetest/calltrace_test.go
+++ b/eth/tracers/internal/tracetest/calltrace_test.go
@@ -112,6 +112,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
} else if err := json.Unmarshal(blob, test); err != nil {
t.Fatalf("failed to parse testcase: %v", err)
}
+ test.Genesis.Config = ensureTracerChainConfig(test.Genesis.Config)
if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil {
t.Fatalf("failed to parse testcase input: %v", err)
}
@@ -139,7 +140,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if tracer.Hooks != nil {
logState = state.NewHookedState(st, tracer.Hooks)
}
- msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee)
+ msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee, test.Genesis.Config)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
@@ -205,6 +206,7 @@ func BenchmarkTracers(b *testing.B) {
if err := json.Unmarshal(blob, test); err != nil {
b.Fatalf("failed to parse testcase: %v", err)
}
+ test.Genesis.Config = ensureTracerChainConfig(test.Genesis.Config)
benchTracer("callTracer", test, b)
})
}
@@ -218,7 +220,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
}
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
context := test.Context.toBlockContext(test.Genesis)
- msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee)
+ msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee, test.Genesis.Config)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
@@ -383,7 +385,7 @@ func TestInternals(t *testing.T) {
t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err)
}
evm := vm.NewEVM(context, logState, nil, config, vm.Config{Tracer: tc.tracer.Hooks})
- msg, err := core.TransactionToMessage(tx, signer, nil, nil, big.NewInt(0))
+ msg, err := core.TransactionToMessage(tx, signer, nil, nil, big.NewInt(0), config)
if err != nil {
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
}
@@ -436,6 +438,7 @@ func testContractTracer(tracerName string, dirPath string, t *testing.T) {
} else if err := json.Unmarshal(blob, test); err != nil {
t.Fatalf("failed to parse testcase: %v", err)
}
+ test.Genesis.Config = ensureTracerChainConfig(test.Genesis.Config)
if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil {
t.Fatalf("failed to parse testcase input: %v", err)
}
@@ -459,7 +462,7 @@ func testContractTracer(tracerName string, dirPath string, t *testing.T) {
t.Fatalf("failed to create call tracer: %v", err)
}
evm := vm.NewEVM(context, state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
- msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil)
+ msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil, test.Genesis.Config)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go
index d65895befdf4..b2820cfc1480 100644
--- a/eth/tracers/internal/tracetest/flat_calltrace_test.go
+++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go
@@ -78,6 +78,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
if err := json.Unmarshal(blob, test); err != nil {
return fmt.Errorf("failed to parse testcase: %v", err)
}
+ test.Genesis.Config = ensureTracerChainConfig(test.Genesis.Config)
// Configure a blockchain with the given prestate
tx := new(types.Transaction)
if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil {
@@ -101,7 +102,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
return fmt.Errorf("failed to create call tracer: %v", err)
}
- msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee)
+ msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee, test.Genesis.Config)
if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
}
diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go
index c418921d6b3f..d70eabcdb81a 100644
--- a/eth/tracers/internal/tracetest/prestate_test.go
+++ b/eth/tracers/internal/tracetest/prestate_test.go
@@ -86,6 +86,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
} else if err := json.Unmarshal(blob, test); err != nil {
t.Fatalf("failed to parse testcase: %v", err)
}
+ test.Genesis.Config = ensureTracerChainConfig(test.Genesis.Config)
if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil {
t.Fatalf("failed to parse testcase input: %v", err)
}
@@ -110,7 +111,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
t.Fatalf("failed to create call tracer: %v", err)
}
- msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee)
+ msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee, test.Genesis.Config)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json
index 877b9b035947..53a4f19b0a52 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json
@@ -1,32 +1,30 @@
{
- "genesis": {
- "difficulty": "4671584",
- "extraData": "0xd683010b05846765746886676f312e3133856c696e7578",
- "gasLimit": "9435026",
- "hash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b",
+ "context": {
+ "difficulty": "4669303",
+ "gasLimit": "9444238",
"miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
- "mixHash": "0x3a44525624571c31344ba57780f7664098fe7cbeafe532bcdee76a23fc474ba0",
- "nonce": "0x6dca647c00c72bbf",
- "number": "1555278",
- "stateRoot": "0x5f56d8323ee384b0c8d1de49d63e150e17283eea813483698362bc0ec9e0242a",
- "timestamp": "1590795319",
- "totalDifficulty": "2242614315030",
+ "number": "1555279",
+ "timestamp": "1590795340"
+ },
+ "genesis": {
"alloc": {
"0x0000000000000000000000000000000000000004": {
"balance": "0x0",
- "nonce": "0",
"code": "0x",
+ "nonce": "0",
"storage": {}
},
"0x877bd459c9b7d8576b44e59e09d076c25946f443": {
"balance": "0x62436e941792f02a5fb1",
- "nonce": "265356",
"code": "0x",
+ "nonce": "265356",
"storage": {}
}
},
"config": {
+ "byzantiumBlock": 0,
"chainId": 63,
+ "constantinopleBlock": 301243,
"daoForkSupport": true,
"eip150Block": 0,
"eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
@@ -34,57 +32,62 @@
"eip158Block": 0,
"ethash": {},
"homesteadBlock": 0,
- "byzantiumBlock": 0,
- "constantinopleBlock": 301243,
- "petersburgBlock": 999983,
- "istanbulBlock": 999983
- }
- },
- "context": {
- "number": "1555279",
- "difficulty": "4669303",
- "timestamp": "1590795340",
- "gasLimit": "9444238",
- "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443"
+ "istanbulBlock": 999983,
+ "petersburgBlock": 999983
+ },
+ "difficulty": "4671584",
+ "extraData": "0xd683010b05846765746886676f312e3133856c696e7578",
+ "gasLimit": "9435026",
+ "hash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b",
+ "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
+ "mixHash": "0x3a44525624571c31344ba57780f7664098fe7cbeafe532bcdee76a23fc474ba0",
+ "nonce": "0x6dca647c00c72bbf",
+ "number": "1555278",
+ "stateRoot": "0x5f56d8323ee384b0c8d1de49d63e150e17283eea813483698362bc0ec9e0242a",
+ "timestamp": "1590795319",
+ "totalDifficulty": "2242614315030"
},
"input": "0xf86f83040c8c843b9aca0083019f7880809b60206000600060006013600462030d40f26002556000516000550081a2a086ad228c89ad9664287b12a5602a635a803506904f4ce39795990ac4f945cd57a025b30ea8042d773f6c5b13d7cc1b3979f9f10ee674410b6a2112ce840d0302dc",
"result": [
{
- "type": "create",
"action": {
"creationMethod": "create",
"from": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
- "value": "0x0",
"gas": "0x19f78",
- "init": "0x60206000600060006013600462030d40f260025560005160005500"
+ "init": "0x60206000600060006013600462030d40f260025560005160005500",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"result": {
- "gasUsed": "0xf800",
+ "address": "0x5f8a7e007172ba80afbff1b15f800eb0b260f224",
"code": "0x",
- "address": "0x5f8a7e007172ba80afbff1b15f800eb0b260f224"
+ "gasUsed": "0xf800"
},
- "traceAddress": [],
"subtraces": 1,
- "transactionPosition": 74,
- "transactionHash": "0x5ef60b27ac971c22a7d484e546e50093ca62300c8986d165154e47773764b6a4",
- "blockNumber": 1555279,
- "blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46"
+ "traceAddress": [],
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "create"
},
{
"action": {
- "balance": "0x0",
"callType": "callcode",
"from": "0x5f8a7e007172ba80afbff1b15f800eb0b260f224",
"gas": "0xab31",
+ "input": "0x",
"to": "0x0000000000000000000000000000000000000004",
"value": "0x13"
},
+ "blockHash": null,
+ "blockNumber": 0,
"error": "insufficient balance for transfer",
- "result": {},
"subtraces": 0,
"traceAddress": [
0
],
+ "transactionHash": null,
+ "transactionPosition": 0,
"type": "call"
}
]
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json
index 1136bcd8e319..d2ffd0861ceb 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json
@@ -1,32 +1,30 @@
{
- "genesis": {
+ "context": {
"difficulty": "4671584",
- "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578",
- "gasLimit": "9425823",
- "hash": "0x27dd7d052dbc8a29cc5b9487e1e41d842e7a643fcaea4964caa22b834964acaf",
- "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3",
- "mixHash": "0xb4a050624f5d147fdf02857cbfd55da3ddc1451743acc5c163861584589c3034",
- "nonce": "0x3c255875b17e0573",
- "number": "1555277",
- "stateRoot": "0x6290d79215a2eebc25d5e456b35876c6d78ffc1ea47bdd70e375ebb3cf325620",
- "timestamp": "1590795308",
- "totalDifficulty": "2242609643446",
+ "gasLimit": "9435026",
+ "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
+ "number": "1555278",
+ "timestamp": "1590795319"
+ },
+ "genesis": {
"alloc": {
"0x0000000000000000000000000000000000000001": {
"balance": "0x0",
- "nonce": "0",
"code": "0x",
+ "nonce": "0",
"storage": {}
},
"0x877bd459c9b7d8576b44e59e09d076c25946f443": {
"balance": "0x624329308610ab365fb1",
- "nonce": "265194",
"code": "0x",
+ "nonce": "265194",
"storage": {}
}
},
"config": {
+ "byzantiumBlock": 0,
"chainId": 63,
+ "constantinopleBlock": 301243,
"daoForkSupport": true,
"eip150Block": 0,
"eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
@@ -34,59 +32,63 @@
"eip158Block": 0,
"ethash": {},
"homesteadBlock": 0,
- "byzantiumBlock": 0,
- "constantinopleBlock": 301243,
- "petersburgBlock": 999983,
- "istanbulBlock": 999983
- }
- },
- "context": {
- "number": "1555278",
+ "istanbulBlock": 999983,
+ "petersburgBlock": 999983
+ },
"difficulty": "4671584",
- "timestamp": "1590795319",
- "gasLimit": "9435026",
- "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443"
+ "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578",
+ "gasLimit": "9425823",
+ "hash": "0x27dd7d052dbc8a29cc5b9487e1e41d842e7a643fcaea4964caa22b834964acaf",
+ "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3",
+ "mixHash": "0xb4a050624f5d147fdf02857cbfd55da3ddc1451743acc5c163861584589c3034",
+ "nonce": "0x3c255875b17e0573",
+ "number": "1555277",
+ "stateRoot": "0x6290d79215a2eebc25d5e456b35876c6d78ffc1ea47bdd70e375ebb3cf325620",
+ "timestamp": "1590795308",
+ "totalDifficulty": "2242609643446"
},
"input": "0xf8ee83040bea843b9aca008301a7588080b8997f18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c600052601c6020527f73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f6040527feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549606052602060806080600060006001610bb7f260025560a060020a6080510660005560005432146001550081a1a05b9a162d84bfe84faa7c176e21c26c0083645d4dd0d566547b7be2c2da0b4259a05b37ff12a4c27634cb0da6008d9b69726d415ff4694f9bc38c7806eb1fb60ae9",
"result": [
{
- "type": "create",
"action": {
"creationMethod": "create",
"from": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
- "value": "0x0",
"gas": "0x1a758",
- "init": "0x7f18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c600052601c6020527f73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f6040527feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549606052602060806080600060006001610bb7f260025560a060020a60805106600055600054321460015500"
+ "init": "0x7f18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c600052601c6020527f73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f6040527feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549606052602060806080600060006001610bb7f260025560a060020a60805106600055600054321460015500",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"result": {
- "gasUsed": "0x111c5",
+ "address": "0x568c19ecb14b87e4aec29b4d2d700a3ad3fd0613",
"code": "0x",
- "address": "0x568c19ecb14b87e4aec29b4d2d700a3ad3fd0613"
+ "gasUsed": "0x111c5"
},
- "traceAddress": [],
"subtraces": 1,
- "transactionPosition": 141,
- "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1",
- "blockNumber": 1555278,
- "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b"
+ "traceAddress": [],
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "create"
},
{
- "type": "call",
"action": {
+ "callType": "callcode",
"from": "0x568c19ecb14b87e4aec29b4d2d700a3ad3fd0613",
- "to": "0x0000000000000000000000000000000000000001",
- "value": "0x0",
"gas": "0xbb7",
"input": "0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
- "callType": "callcode"
+ "to": "0x0000000000000000000000000000000000000001",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"error": "out of gas",
- "traceAddress": [0],
"subtraces": 0,
- "transactionPosition": 141,
- "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1",
- "blockNumber": 1555278,
- "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b"
+ "traceAddress": [
+ 0
+ ],
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "call"
}
]
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json
index 87e002b4edb6..7468a4b1f496 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json
@@ -1,32 +1,30 @@
{
- "genesis": {
+ "context": {
"difficulty": "4683014",
- "extraData": "0x537465762d63676574682d76312e31312e34",
- "gasLimit": "9435044",
- "hash": "0x3452ca5005cb73cd60dfa488a7b124251168e564491f80eb66765e79d78cfd95",
- "miner": "0x415aa6292d1db797a467b22139704956c030e62f",
- "mixHash": "0x6037612618507ae70c74a72bc2580253662971db959cfbc06d3f8527d4d01575",
- "nonce": "0x314fc90dee5e39a2",
- "number": "1555274",
- "stateRoot": "0x795751f3f96a5de1fd3944ddd78cbfe4ef10491e1086be47609869a30929d0e5",
- "timestamp": "1590795228",
- "totalDifficulty": "2242595605834",
+ "gasLimit": "9444256",
+ "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
+ "number": "1555275",
+ "timestamp": "1590795244"
+ },
+ "genesis": {
"alloc": {
"0x0000000000000000000000000000000000000009": {
"balance": "0x0",
- "nonce": "0",
"code": "0x",
+ "nonce": "0",
"storage": {}
},
"0x877bd459c9b7d8576b44e59e09d076c25946f443": {
"balance": "0x6242e3ccf48e66425fb1",
- "nonce": "264981",
"code": "0x",
+ "nonce": "264981",
"storage": {}
}
},
"config": {
+ "byzantiumBlock": 0,
"chainId": 63,
+ "constantinopleBlock": 301243,
"daoForkSupport": true,
"eip150Block": 0,
"eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
@@ -34,55 +32,59 @@
"eip158Block": 0,
"ethash": {},
"homesteadBlock": 0,
- "byzantiumBlock": 0,
- "constantinopleBlock": 301243,
- "petersburgBlock": 999983,
- "istanbulBlock": 999983
- }
- },
- "context": {
- "number": "1555275",
+ "istanbulBlock": 999983,
+ "petersburgBlock": 999983
+ },
"difficulty": "4683014",
- "timestamp": "1590795244",
- "gasLimit": "9444256",
- "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443"
+ "extraData": "0x537465762d63676574682d76312e31312e34",
+ "gasLimit": "9435044",
+ "hash": "0x3452ca5005cb73cd60dfa488a7b124251168e564491f80eb66765e79d78cfd95",
+ "miner": "0x415aa6292d1db797a467b22139704956c030e62f",
+ "mixHash": "0x6037612618507ae70c74a72bc2580253662971db959cfbc06d3f8527d4d01575",
+ "nonce": "0x314fc90dee5e39a2",
+ "number": "1555274",
+ "stateRoot": "0x795751f3f96a5de1fd3944ddd78cbfe4ef10491e1086be47609869a30929d0e5",
+ "timestamp": "1590795228",
+ "totalDifficulty": "2242595605834"
},
"input": "0xf87a83040b15843b9aca008301a0348080a636600060003760406103e8366000600060095af26001556103e851600255610408516003550081a1a0dd883fbbb489b640dadc8c1bf151767155228d0a1321f687f070f35f14374b05a02dd0ccb16a8de39bc8ee61381bbbbb54f0ab18422afd7b03c6163da1f5023934",
"result": [
{
- "type": "create",
"action": {
"creationMethod": "create",
"from": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
- "value": "0x0",
"gas": "0x1a034",
- "init": "0x36600060003760406103e8366000600060095af26001556103e8516002556104085160035500"
+ "init": "0x36600060003760406103e8366000600060095af26001556103e8516002556104085160035500",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"error": "out of gas: not enough gas for reentrancy sentry",
- "traceAddress": [],
"subtraces": 1,
- "transactionPosition": 117,
- "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9",
- "blockNumber": 1555275,
- "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd"
+ "traceAddress": [],
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "create"
},
{
- "type": "call",
"action": {
+ "callType": "callcode",
"from": "0x8832ef498070145c3a5b30f47fbca71fd7b1de9f",
- "to": "0x0000000000000000000000000000000000000009",
- "value": "0x0",
"gas": "0xc1fe",
"input": "0x",
- "callType": "callcode"
+ "to": "0x0000000000000000000000000000000000000009",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"error": "invalid input length",
- "traceAddress": [0],
"subtraces": 0,
- "transactionPosition": 117,
- "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9",
- "blockNumber": 1555275,
- "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd"
+ "traceAddress": [
+ 0
+ ],
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "call"
}
]
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json
index 1e421abc76b1..9396ec99e075 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json
@@ -1,32 +1,30 @@
{
+ "context": {
+ "difficulty": "4642198",
+ "gasLimit": "9289249",
+ "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
+ "number": "1555170",
+ "timestamp": "1590794112"
+ },
"genesis": {
- "difficulty": "4639933",
- "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578",
- "gasLimit": "9280188",
- "hash": "0x9a5f3a98eb1c60f6e3f450658a9cea190157e7021d04f927b752ad6482cf9194",
- "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3",
- "mixHash": "0x6b6f8fcaa54b8565c4c1ae7cf0a020e938a53007f4561e758b17bc05c9044d78",
- "nonce": "0x773aba50dc51b462",
- "number": "1555169",
- "stateRoot": "0xc4b9703de3e59ff795baae2c3afa010cf039c37244a7a6af7f3f491a10601348",
- "timestamp": "1590794111",
- "totalDifficulty": "2242105342155",
"alloc": {
"0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d": {
"balance": "0x0",
- "nonce": "0",
"code": "0x",
+ "nonce": "0",
"storage": {}
},
"0x877bd459c9b7d8576b44e59e09d076c25946f443": {
"balance": "0x62325b40cbbd0915c4b9",
- "nonce": "260875",
"code": "0x",
+ "nonce": "260875",
"storage": {}
}
},
"config": {
+ "byzantiumBlock": 0,
"chainId": 63,
+ "constantinopleBlock": 301243,
"daoForkSupport": true,
"eip150Block": 0,
"eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
@@ -34,60 +32,62 @@
"eip158Block": 0,
"ethash": {},
"homesteadBlock": 0,
- "byzantiumBlock": 0,
- "constantinopleBlock": 301243,
- "petersburgBlock": 999983,
- "istanbulBlock": 999983
- }
- },
- "context": {
- "number": "1555170",
- "difficulty": "4642198",
- "timestamp": "1590794112",
- "gasLimit": "9289249",
- "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443"
+ "istanbulBlock": 999983,
+ "petersburgBlock": 999983
+ },
+ "difficulty": "4639933",
+ "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578",
+ "gasLimit": "9280188",
+ "hash": "0x9a5f3a98eb1c60f6e3f450658a9cea190157e7021d04f927b752ad6482cf9194",
+ "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3",
+ "mixHash": "0x6b6f8fcaa54b8565c4c1ae7cf0a020e938a53007f4561e758b17bc05c9044d78",
+ "nonce": "0x773aba50dc51b462",
+ "number": "1555169",
+ "stateRoot": "0xc4b9703de3e59ff795baae2c3afa010cf039c37244a7a6af7f3f491a10601348",
+ "timestamp": "1590794111",
+ "totalDifficulty": "2242105342155"
},
"input": "0xf8658303fb0b843b9aca0083019ee48080915a600055600060006000f0505a6001550081a2a01a7deb3a16d967b766459ef486b00656c6581e5ad58968184a33701e27e0eb8aa07162ccdfe2018d64360a605310a62c399dd586c7282dd42a88c54f02f51d451f",
"result": [
{
- "type": "create",
"action": {
"creationMethod": "create",
"from": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
- "value": "0x0",
"gas": "0x19ee4",
- "init": "0x5a600055600060006000f0505a60015500"
+ "init": "0x5a600055600060006000f0505a60015500",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"error": "out of gas: not enough gas for reentrancy sentry",
- "traceAddress": [],
"subtraces": 1,
- "transactionPosition": 63,
- "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650",
- "blockNumber": 1555170,
- "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e"
+ "traceAddress": [],
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "create"
},
{
- "type": "create",
"action": {
"creationMethod": "create",
"from": "0x9c5cfe45b15eaff4ad617af4250189e26024a4f8",
- "value": "0x0",
"gas": "0x165",
- "init": "0x"
+ "init": "0x",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"result": {
- "gasUsed": "0x0",
+ "address": "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d",
"code": "0x",
- "address": "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d"
+ "gasUsed": "0x0"
},
+ "subtraces": 0,
"traceAddress": [
0
],
- "subtraces": 0,
- "transactionPosition": 63,
- "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650",
- "blockNumber": 1555170,
- "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e"
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "create"
}
]
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json
index a61e83adcadc..cf891e31b39f 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json
@@ -1,32 +1,30 @@
{
- "genesis": {
- "difficulty": "4673862",
- "extraData": "0xd683010b05846765746886676f312e3133856c696e7578",
- "gasLimit": "9471919",
- "hash": "0x7f072150c5905c214966e3432d418910badcdbe510aceaac295b1d7059cc0ffc",
+ "context": {
+ "difficulty": "4676144",
+ "gasLimit": "9481167",
"miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
- "mixHash": "0x113ced8fedb939fdc862008da7bdddde726f997c0e6dfba0e55613994757b489",
- "nonce": "0x0f411a2e5552c5b7",
- "number": "1555284",
- "stateRoot": "0x9fe125b361b72d5479b24ad9be9964b74228c73a2dfb0065060a79b4a6dfaa1e",
- "timestamp": "1590795374",
- "totalDifficulty": "2242642335405",
+ "number": "1555285",
+ "timestamp": "1590795378"
+ },
+ "genesis": {
"alloc": {
- "0xe85df1413eebe1b191c26260e19783a274a6b041": {
- "balance": "0x0",
- "nonce": "0",
- "code": "0x",
- "storage": {}
- },
"0x877bd459c9b7d8576b44e59e09d076c25946f443": {
"balance": "0x6244c985ef1e48e84531",
+ "code": "0x",
"nonce": "265775",
+ "storage": {}
+ },
+ "0xe85df1413eebe1b191c26260e19783a274a6b041": {
+ "balance": "0x0",
"code": "0x",
+ "nonce": "0",
"storage": {}
}
},
"config": {
+ "byzantiumBlock": 0,
"chainId": 63,
+ "constantinopleBlock": 301243,
"daoForkSupport": true,
"eip150Block": 0,
"eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
@@ -34,37 +32,39 @@
"eip158Block": 0,
"ethash": {},
"homesteadBlock": 0,
- "byzantiumBlock": 0,
- "constantinopleBlock": 301243,
- "petersburgBlock": 999983,
- "istanbulBlock": 999983
- }
- },
- "context": {
- "number": "1555285",
- "difficulty": "4676144",
- "timestamp": "1590795378",
- "gasLimit": "9481167",
- "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443"
+ "istanbulBlock": 999983,
+ "petersburgBlock": 999983
+ },
+ "difficulty": "4673862",
+ "extraData": "0xd683010b05846765746886676f312e3133856c696e7578",
+ "gasLimit": "9471919",
+ "hash": "0x7f072150c5905c214966e3432d418910badcdbe510aceaac295b1d7059cc0ffc",
+ "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
+ "mixHash": "0x113ced8fedb939fdc862008da7bdddde726f997c0e6dfba0e55613994757b489",
+ "nonce": "0x0f411a2e5552c5b7",
+ "number": "1555284",
+ "stateRoot": "0x9fe125b361b72d5479b24ad9be9964b74228c73a2dfb0065060a79b4a6dfaa1e",
+ "timestamp": "1590795374",
+ "totalDifficulty": "2242642335405"
},
"input": "0xf9014083040e2f843b9aca008301aab08080b8eb7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5547f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000037f05581a2a09db45e7846f193471f6d897fb6ff58b7ec41a9c6f63d10aca47d821c365981cba052ec320875625e16141a1a9e8b7993de863698fb699f93ae2cab26149bbb144f",
"result": [
{
- "type": "create",
"action": {
"creationMethod": "create",
"from": "0x877bd459c9b7d8576b44e59e09d076c25946f443",
- "value": "0x0",
"gas": "0x1aab0",
- "init": "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5547f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000037f055"
+ "init": "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5547f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000037f055",
+ "value": "0x0"
},
+ "blockHash": null,
+ "blockNumber": 0,
"error": "out of gas",
- "traceAddress": [],
"subtraces": 1,
- "transactionPosition": 16,
- "transactionHash": "0x384487e5ae8d2997aece8e28403d393cb9752425e6de358891bed981c5af1c05",
- "blockNumber": 1555285,
- "blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f"
+ "traceAddress": [],
+ "transactionHash": null,
+ "transactionPosition": 0,
+ "type": "create"
},
{
"action": {
@@ -74,12 +74,15 @@
"init": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"value": "0xc350"
},
+ "blockHash": null,
+ "blockNumber": 0,
"error": "insufficient balance for transfer",
- "result": {},
"subtraces": 0,
"traceAddress": [
0
],
+ "transactionHash": null,
+ "transactionPosition": 0,
"type": "create"
}
]
diff --git a/eth/tracers/internal/tracetest/util.go b/eth/tracers/internal/tracetest/util.go
index 94799609ef5c..d43c4b42440d 100644
--- a/eth/tracers/internal/tracetest/util.go
+++ b/eth/tracers/internal/tracetest/util.go
@@ -9,6 +9,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/common/math"
"github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/core/vm"
+ "github.com/XinFinOrg/XDPoSChain/params"
// Force-load native and js packages, to trigger registration
_ "github.com/XinFinOrg/XDPoSChain/eth/tracers/js"
@@ -24,6 +25,19 @@ func camel(str string) string {
return strings.Join(pieces, "")
}
+func ensureTracerChainConfig(config *params.ChainConfig) *params.ChainConfig {
+ defaultTIPTRC21FeeBlock := common.CloneBigInt(params.XDCMainnetChainConfig.TIPTRC21FeeBlock)
+ if config == nil {
+ return ¶ms.ChainConfig{TIPTRC21FeeBlock: defaultTIPTRC21FeeBlock}
+ }
+ if config.TIPTRC21FeeBlock != nil {
+ return config
+ }
+ clone := *config
+ clone.TIPTRC21FeeBlock = defaultTIPTRC21FeeBlock
+ return &clone
+}
+
type callContext struct {
Number math.HexOrDecimal64 `json:"number"`
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go
index 6795721725cf..f2c9520b1c4a 100644
--- a/eth/tracers/js/tracer_test.go
+++ b/eth/tracers/js/tracer_test.go
@@ -251,24 +251,26 @@ func TestTxStartUsesExecutionGasPrice(t *testing.T) {
func TestIsPrecompile(t *testing.T) {
chaincfg := ¶ms.ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(100),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(200),
- BerlinBlock: big.NewInt(300),
- LondonBlock: big.NewInt(0),
- Ethash: new(params.EthashConfig),
- Clique: nil,
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(100),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(200),
+ TIPXDCXCancellationFeeBlock: big.NewInt(200),
+ BerlinBlock: big.NewInt(300),
+ LondonBlock: big.NewInt(0),
+ Ethash: new(params.EthashConfig),
+ Clique: nil,
}
chaincfg.ByzantiumBlock = big.NewInt(100)
chaincfg.IstanbulBlock = big.NewInt(200)
+ chaincfg.TIPXDCXCancellationFeeBlock = big.NewInt(200)
chaincfg.BerlinBlock = big.NewInt(300)
txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil, chaincfg)
@@ -292,7 +294,7 @@ func TestIsPrecompile(t *testing.T) {
t.Error(err)
}
if string(res) != "true" {
- t.Errorf("tracer should consider blake2f as precompile in istanbul")
+ t.Errorf("tracer should consider blake2f as precompile after TIPXDCXCancellationFee")
}
}
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index fe2764a45148..3df37b4ba74d 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -79,7 +79,7 @@ func BenchmarkTransactionTraceV2(b *testing.B) {
evm := vm.NewEVM(context, state, nil, params.AllEthashProtocolChanges, vm.Config{})
- msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee)
+ msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee, params.AllEthashProtocolChanges)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go
index ba4f8fa0f342..1f2ff1ff0c68 100644
--- a/ethclient/ethclient_test.go
+++ b/ethclient/ethclient_test.go
@@ -85,8 +85,6 @@ var testChainConfig = func() *params.ChainConfig {
if config.Eip1559Block == nil {
config.Eip1559Block = big.NewInt(0)
}
- // Ensure global chain constants match the test chain config.
- common.CopyConstants(config.ChainID.Uint64())
return &config
}()
diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go
index 9f8deb41bca7..209514f6e957 100644
--- a/ethclient/gethclient/gethclient_test.go
+++ b/ethclient/gethclient/gethclient_test.go
@@ -98,9 +98,6 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block, []common.Hash) {
func generateTestChain() (*core.Genesis, []*types.Block, []common.Hash) {
chainConfig := *params.AllEthashProtocolChanges
- chainConfig.Eip1559Block = big.NewInt(0)
- // Ensure global chain constants match the test chain config before block generation.
- common.CopyConstants(chainConfig.ChainID.Uint64())
genesis := &core.Genesis{
Config: &chainConfig,
Alloc: types.GenesisAlloc{
diff --git a/ethclient/simulated/backend.go b/ethclient/simulated/backend.go
index 10248deaf7d7..00a9805ed2b4 100644
--- a/ethclient/simulated/backend.go
+++ b/ethclient/simulated/backend.go
@@ -273,6 +273,7 @@ func (b *Backend) rollback(parent *types.Block) {
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database())
+ b.pendingState.SetChainConfig(b.config)
}
// Fork creates a side-chain that can be used to simulate reorgs.
@@ -1031,6 +1032,7 @@ func (b *Backend) SendTransaction(ctx context.Context, tx *types.Transaction) er
}
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database())
+ b.pendingState.SetChainConfig(b.config)
b.pendingReceipts = receipts[0]
return nil
}
@@ -1164,6 +1166,7 @@ func (b *Backend) AdjustTime(adjustment time.Duration) error {
stateDB, _ := b.blockchain.State()
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database())
+ b.pendingState.SetChainConfig(b.config)
return nil
}
diff --git a/internal/configapi/configapi.go b/internal/configapi/configapi.go
new file mode 100644
index 000000000000..5689c371a8d4
--- /dev/null
+++ b/internal/configapi/configapi.go
@@ -0,0 +1,117 @@
+package configapi
+
+import (
+ "context"
+ "fmt"
+ "math/big"
+ "slices"
+
+ "github.com/XinFinOrg/XDPoSChain/common"
+ "github.com/XinFinOrg/XDPoSChain/common/hexutil"
+ "github.com/XinFinOrg/XDPoSChain/core/forkid"
+ "github.com/XinFinOrg/XDPoSChain/core/types"
+ "github.com/XinFinOrg/XDPoSChain/core/vm"
+ "github.com/XinFinOrg/XDPoSChain/params"
+ "github.com/XinFinOrg/XDPoSChain/rpc"
+)
+
+type Backend interface {
+ HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
+ CurrentHeader() *types.Header
+ ChainConfig() *params.ChainConfig
+}
+
+type ConfigEntry struct {
+ ActivationBlock uint64 `json:"activationBlock"`
+ ChainId *hexutil.Big `json:"chainId"`
+ ForkId hexutil.Bytes `json:"forkId"`
+ ActiveForks []string `json:"activeForks"`
+ Precompiles map[string]common.Address `json:"precompiles"`
+ SystemContracts map[string]common.Address `json:"systemContracts"`
+}
+
+type ConfigResponse struct {
+ Current *ConfigEntry `json:"current"`
+ Next *ConfigEntry `json:"next"`
+ Last *ConfigEntry `json:"last"`
+}
+
+func Build(ctx context.Context, backend Backend) (*ConfigResponse, error) {
+ genesis, err := backend.HeaderByNumber(ctx, 0)
+ if err != nil {
+ return nil, fmt.Errorf("unable to load genesis: %w", err)
+ }
+ if genesis == nil {
+ return nil, fmt.Errorf("unable to load genesis: nil header")
+ }
+ genesisBlock := types.NewBlockWithHeader(genesis)
+
+ current := backend.CurrentHeader()
+ if current == nil {
+ return nil, fmt.Errorf("unable to load current header: nil header")
+ }
+ if current.Number == nil {
+ return nil, fmt.Errorf("unable to load current header: nil number")
+ }
+ cfg := backend.ChainConfig()
+ if cfg == nil {
+ return nil, fmt.Errorf("unable to load chain config: nil config")
+ }
+
+ currentBlock, nextBlock, lastBlock := configBlocks(cfg, current.Number.Uint64())
+ resp := ConfigResponse{
+ Current: assembleConfig(cfg, genesisBlock, currentBlock),
+ Next: assembleConfig(cfg, genesisBlock, nextBlock),
+ Last: assembleConfig(cfg, genesisBlock, lastBlock),
+ }
+ if resp.Next == nil {
+ resp.Last = nil
+ }
+ return &resp, nil
+}
+
+func configBlocks(cfg *params.ChainConfig, head uint64) (*big.Int, *big.Int, *big.Int) {
+ forkBlocks := cfg.GatherForks()
+ if len(forkBlocks) == 0 {
+ return new(big.Int), nil, nil
+ }
+ idx, found := slices.BinarySearch(forkBlocks, head)
+ if found {
+ idx++
+ }
+
+ current := new(big.Int)
+ if idx > 0 {
+ current.SetUint64(forkBlocks[idx-1])
+ }
+
+ var next *big.Int
+ if idx < len(forkBlocks) {
+ next = new(big.Int).SetUint64(forkBlocks[idx])
+ }
+
+ last := new(big.Int).SetUint64(forkBlocks[len(forkBlocks)-1])
+ return current, next, last
+}
+
+func assembleConfig(cfg *params.ChainConfig, genesis *types.Block, num *big.Int) *ConfigEntry {
+ if num == nil {
+ return nil
+ }
+
+ rules := cfg.Rules(num)
+ precompiles := make(map[string]common.Address)
+ for addr, precompile := range vm.ActivePrecompiledContracts(rules) {
+ precompiles[precompile.Name()] = addr
+ }
+ block := num.Uint64()
+ id := forkid.NewID(cfg, genesis, block).Hash
+ return &ConfigEntry{
+ ActivationBlock: block,
+ ChainId: (*hexutil.Big)(cfg.ChainID),
+ ForkId: id[:],
+ ActiveForks: cfg.ActiveForks(num),
+ Precompiles: precompiles,
+ SystemContracts: cfg.ActiveSystemContracts(block),
+ }
+}
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index d342946ac3a9..de6729edeabd 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -736,7 +736,7 @@ func (api *BlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAddres
return result, errors.New("undefined XDPoS consensus engine")
}
} else if api.b.ChainConfig().IsTIPIncreaseMasternodes(block.Number()) {
- maxMasternodes = common.MaxMasternodesV2
+ maxMasternodes = api.b.ChainConfig().XDPoS.MaxMasternodesV2
} else {
maxMasternodes = common.MaxMasternodes
}
@@ -931,7 +931,7 @@ func (api *BlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.EpochNumb
return result, errors.New("undefined XDPoS consensus engine")
}
} else if api.b.ChainConfig().IsTIPIncreaseMasternodes(block.Number()) {
- maxMasternodes = common.MaxMasternodesV2
+ maxMasternodes = api.b.ChainConfig().XDPoS.MaxMasternodesV2
} else {
maxMasternodes = common.MaxMasternodes
}
diff --git a/internal/ethapi/override/override_test.go b/internal/ethapi/override/override_test.go
index 1d41028b4405..8818c32ef834 100644
--- a/internal/ethapi/override/override_test.go
+++ b/internal/ethapi/override/override_test.go
@@ -33,6 +33,10 @@ func (p *precompileContract) RequiredGas(input []byte) uint64 { return 0 }
func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil }
+func (p *precompileContract) Name() string {
+ return "test-implement"
+}
+
func TestStateOverrideMovePrecompile(t *testing.T) {
db := state.NewDatabase(rawdb.NewMemoryDatabase())
statedb, err := state.New(common.Hash{}, db)
diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go
index 173ae9b06179..5b194406b9ff 100644
--- a/internal/ethapi/transaction_args_test.go
+++ b/internal/ethapi/transaction_args_test.go
@@ -252,6 +252,7 @@ func newBackendMock() *backendMock {
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
Eip1559Block: big.NewInt(1000),
}
diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go
index 2fee8d4fa852..6f402fb34dae 100644
--- a/internal/web3ext/web3ext.go
+++ b/internal/web3ext/web3ext.go
@@ -79,6 +79,11 @@ const XdposJs = `
web3._extend({
property: 'XDPoS',
methods: [
+ new web3._extend.Method({
+ name: 'getConfig',
+ call: 'XDPoS_getConfig',
+ params: 0,
+ }),
new web3._extend.Method({
name: 'getSnapshot',
call: 'XDPoS_getSnapshot',
diff --git a/miner/worker.go b/miner/worker.go
index 2ed32a7332b2..8d640cbdb74e 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -849,7 +849,7 @@ func (w *worker) commitNewWork() {
Extra: w.extra,
Time: uint64(tstamp),
}
- if w.chainConfig.IsDynamicGasLimitBlock(header.Number) {
+ if w.chainConfig.IsDynamicGasLimit(header.Number) {
header.GasLimit = core.CalcGasLimit(parent.GasLimit(), w.config.GasCeil)
} else {
header.GasLimit = w.config.GasCeil
@@ -894,7 +894,7 @@ func (w *worker) commitNewWork() {
if w.chainConfig.DAOForkSupport && w.chainConfig.DAOForkBlock != nil && w.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 {
misc.ApplyDAOHardFork(work.state)
}
- if common.TIPSigning.Cmp(header.Number) == 0 {
+ if w.chainConfig.TIPSigningBlock != nil && w.chainConfig.TIPSigningBlock.Cmp(header.Number) == 0 {
work.state.DeleteAddress(common.BlockSignersBinary)
}
if w.chainConfig.IsPrague(header.Number) {
@@ -1100,7 +1100,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
continue
}
to := tx.To()
- if w.header.Number.Uint64() >= common.DenylistHFNumber {
+ if w.config.IsDenylist(w.header.Number) {
from := tx.From()
// check if sender is in denylist
if common.IsInDenylist(from) {
@@ -1115,7 +1115,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
}
data := tx.Data()
// validate minFee slot for XDCZ
- if tx.IsXDCZApplyTransaction() {
+ if tx.IsXDCZApplyTransaction(w.config) {
copyState, _ := bc.State()
if err := core.ValidateXDCZApplyTransaction(bc, nil, copyState, common.BytesToAddress(data[4:])); err != nil {
log.Debug("XDCZApply: invalid token", "token", common.BytesToAddress(data[4:]).Hex())
@@ -1123,7 +1123,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
}
}
// validate balance slot, token decimal for XDCX
- if tx.IsXDCXApplyTransaction() {
+ if tx.IsXDCXApplyTransaction(w.config) {
copyState, _ := bc.State()
if err := core.ValidateXDCXApplyTransaction(bc, nil, copyState, common.BytesToAddress(data[4:])); err != nil {
log.Debug("XDCXApply: invalid token", "token", common.BytesToAddress(data[4:]).Hex())
@@ -1186,7 +1186,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
log.Debug("Add Special Transaction failed, account skipped", "hash", hash, "sender", from, "nonce", tx.Nonce(), "to", to, "err", err)
}
if tokenFeeUsed {
- fee := common.GetGasFee(w.header.Number.Uint64(), gas)
+ fee := common.GetGasFee(w.header.Number.Uint64(), gas, w.config.TIPTRC21FeeBlock, w.config.Gas50xBlock)
balanceFee[*to] = new(big.Int).Sub(balanceFee[*to], fee)
balanceUpdated[*to] = balanceFee[*to]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
@@ -1219,7 +1219,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
break
}
to := tx.To()
- if w.header.Number.Uint64() >= common.DenylistHFNumber {
+ if w.config.IsDenylist(w.header.Number) {
from := tx.From()
// check if sender is in denylist
if common.IsInDenylist(from) {
@@ -1236,7 +1236,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
}
data := tx.Data()
// validate minFee slot for XDCZ
- if tx.IsXDCZApplyTransaction() {
+ if tx.IsXDCZApplyTransaction(w.config) {
copyState, _ := bc.State()
if err := core.ValidateXDCZApplyTransaction(bc, nil, copyState, common.BytesToAddress(data[4:])); err != nil {
log.Debug("XDCZApply: invalid token", "token", common.BytesToAddress(data[4:]).Hex())
@@ -1245,7 +1245,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
}
}
// validate balance slot, token decimal for XDCX
- if tx.IsXDCXApplyTransaction() {
+ if tx.IsXDCXApplyTransaction(w.config) {
copyState, _ := bc.State()
if err := core.ValidateXDCXApplyTransaction(bc, nil, copyState, common.BytesToAddress(data[4:])); err != nil {
log.Debug("XDCXApply: invalid token", "token", common.BytesToAddress(data[4:]).Hex())
@@ -1317,7 +1317,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
txs.Shift()
}
if tokenFeeUsed {
- fee := common.GetGasFee(w.header.Number.Uint64(), gas)
+ fee := common.GetGasFee(w.header.Number.Uint64(), gas, w.config.TIPTRC21FeeBlock, w.config.Gas50xBlock)
balanceFee[*to] = new(big.Int).Sub(balanceFee[*to], fee)
balanceUpdated[*to] = balanceFee[*to]
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
diff --git a/miner/worker_test.go b/miner/worker_test.go
index ab901eae53af..c64abea2e42c 100644
--- a/miner/worker_test.go
+++ b/miner/worker_test.go
@@ -84,8 +84,10 @@ func TestWorkerUpdateNonXDPoSStaysRunning(t *testing.T) {
func TestWorkerCheckPreCommitXDPoSMismatch(t *testing.T) {
config := ¶ms.ChainConfig{
- ChainID: big.NewInt(1),
+ ChainID: big.NewInt(1),
+ TIPTRC21FeeBlock: big.NewInt(0),
XDPoS: ¶ms.XDPoSConfig{
+ MaxMasternodesV2: 1, // required to avoid missing fork switch error
V2: ¶ms.V2{
SwitchBlock: big.NewInt(0),
AllConfigs: map[uint64]*params.V2Config{
diff --git a/params/config.go b/params/config.go
index 165436dd559a..421500726a41 100644
--- a/params/config.go
+++ b/params/config.go
@@ -19,23 +19,67 @@ package params
import (
"cmp"
"encoding/json"
+ "errors"
"fmt"
"maps"
"math/big"
+ "reflect"
"slices"
"strings"
"sync"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/log"
+ "github.com/XinFinOrg/XDPoSChain/params/forks"
)
const (
ConsensusEngineVersion1 = "v1"
ConsensusEngineVersion2 = "v2"
Default = 0
+
+ MainnetV2SwitchBlock uint64 = 80370000 // Target 2nd Oct 2024
+ TestnetV2SwitchBlock uint64 = 56828700 // Target 13th Nov 2023
+ DevnetV2SwitchBlock uint64 = 2700
)
+var migratedForkFieldJSONKeys = []string{
+ "tip2019Block",
+ "tipSigningBlock",
+ "tipRandomizeBlock",
+ "tipIncreaseMasternodesBlock",
+ "denylistBlock",
+ "tipNoHalvingMNRewardBlock",
+ "tipXDCXBlock",
+ "tipXDCXLendingBlock",
+ "tipXDCXCancellationFeeBlock",
+ "tipTRC21FeeBlock",
+ "berlinBlock",
+ "londonBlock",
+ "mergeBlock",
+ "shanghaiBlock",
+ "tipXDCXMinerDisableBlock",
+ "tipXDCXReceiverDisableBlock",
+ "eip1559Block",
+ "cancunBlock",
+ "pragueBlock",
+ "osakaBlock",
+ "dynamicGasLimitBlock",
+ "tipUpgradeRewardBlock",
+ "tipUpgradePenaltyBlock",
+ "tipEpochHalvingBlock",
+}
+
+var (
+ ErrMissingForkSwitch = errors.New("missing fork switch")
+ ErrWrongForkSwitchOrder = errors.New("wrong fork switch order")
+)
+
+// MigratedForkFieldJSONKeys returns migrated fork JSON keys as a defensive copy.
+func MigratedForkFieldJSONKeys() []string {
+ return append([]string(nil), migratedForkFieldJSONKeys...)
+}
+
var (
MainnetGenesisHash = common.HexToHash("0x4a9d748bd78a8d0385b67788c2435dcdb914f98a96250b68863a1f8b7642d6b1") // XDC Mainnet genesis hash to enforce below configs on
TestnetGenesisHash = common.HexToHash("0xbdea512b4f12ff1135ec92c00dc047ffb93890c2ea1aa0eefe9b013d80640075") // XDC Testnet genesis hash to enforce below configs on
@@ -167,6 +211,18 @@ var (
},
}
+ LocalnetV2Configs = map[uint64]*V2Config{
+ Default: {
+ MaxMasternodes: 108,
+ SwitchRound: 0,
+ CertThreshold: 0.666,
+ TimeoutSyncThreshold: 3,
+ TimeoutPeriod: 10,
+ MinePeriod: 2,
+ ExpTimeoutConfig: ExpTimeoutConfig{Base: 1.0, MaxExponent: 0},
+ },
+ }
+
UnitTestV2Configs = map[uint64]*V2Config{
Default: {
MaxMasternodes: 18,
@@ -206,12 +262,49 @@ var (
// XDPoSChain mainnet config
XDCMainnetChainConfig = &ChainConfig{
- ChainID: big.NewInt(50),
- HomesteadBlock: big.NewInt(1),
- EIP150Block: big.NewInt(2),
- EIP155Block: big.NewInt(3),
- EIP158Block: big.NewInt(3),
- ByzantiumBlock: big.NewInt(4),
+ Name: "XDCMainnetChainConfig",
+ ChainID: big.NewInt(50),
+ HomesteadBlock: big.NewInt(1),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(1),
+ EIP150Block: big.NewInt(2),
+ EIP155Block: big.NewInt(3),
+ EIP158Block: big.NewInt(3),
+ ByzantiumBlock: big.NewInt(4),
+ ConstantinopleBlock: nil,
+ PetersburgBlock: nil,
+ IstanbulBlock: nil,
+ TIPSigningBlock: big.NewInt(3000000),
+ TIPRandomizeBlock: big.NewInt(3464000),
+ TIPIncreaseMasternodesBlock: big.NewInt(5000000),
+ DenylistBlock: big.NewInt(38383838),
+ TIPNoHalvingMNRewardBlock: big.NewInt(38383838),
+ TIPXDCXBlock: big.NewInt(38383838),
+ TIPXDCXLendingBlock: big.NewInt(38383838),
+ TIPXDCXCancellationFeeBlock: big.NewInt(38383838),
+ TIPTRC21FeeBlock: big.NewInt(38383838),
+ BerlinBlock: big.NewInt(76321000),
+ LondonBlock: big.NewInt(76321000),
+ MergeBlock: big.NewInt(76321000),
+ ShanghaiBlock: big.NewInt(76321000),
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: big.NewInt(80370000),
+ TIPXDCXReceiverDisableBlock: big.NewInt(80370900),
+ Eip1559Block: big.NewInt(98800200),
+ CancunBlock: big.NewInt(98802000),
+ PragueBlock: nil,
+ OsakaBlock: nil,
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: nil,
XDPoS: &XDPoSConfig{
Period: 2,
Epoch: 900,
@@ -219,9 +312,10 @@ var (
RewardCheckpoint: 900,
Gap: 450,
FoundationWalletAddr: common.HexToAddress("xdc92a289fe95a85c53b8d0d113cbaef0c1ec98ac65"),
+ MaxMasternodesV2: 108,
V2: &V2{
- SwitchEpoch: common.MainnetConstant.TIPV2SwitchBlock.Uint64() / 900,
- SwitchBlock: common.MainnetConstant.TIPV2SwitchBlock,
+ SwitchEpoch: MainnetV2SwitchBlock / 900,
+ SwitchBlock: big.NewInt(int64(MainnetV2SwitchBlock)),
CurrentConfig: MainnetV2Configs[0],
AllConfigs: MainnetV2Configs,
},
@@ -230,29 +324,97 @@ var (
// MainnetChainConfig is the chain parameters to run a node on the ethereum main network.
MainnetChainConfig = &ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: big.NewInt(1150000),
- DAOForkBlock: big.NewInt(1920000),
- DAOForkSupport: true,
- EIP150Block: big.NewInt(2463000),
- EIP155Block: big.NewInt(2675000),
- EIP158Block: big.NewInt(2675000),
- ByzantiumBlock: big.NewInt(4370000),
- ConstantinopleBlock: nil,
- Ethash: new(EthashConfig),
+ Name: "MainnetChainConfig",
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(1150000),
+ DAOForkBlock: big.NewInt(1920000),
+ DAOForkSupport: true,
+ TIP2019Block: nil,
+ EIP150Block: big.NewInt(2463000),
+ EIP155Block: big.NewInt(2675000),
+ EIP158Block: big.NewInt(2675000),
+ ByzantiumBlock: big.NewInt(4370000),
+ ConstantinopleBlock: nil,
+ PetersburgBlock: nil,
+ IstanbulBlock: nil,
+ TIPSigningBlock: nil,
+ TIPRandomizeBlock: nil,
+ TIPIncreaseMasternodesBlock: nil,
+ DenylistBlock: nil,
+ TIPNoHalvingMNRewardBlock: nil,
+ TIPXDCXBlock: nil,
+ TIPXDCXLendingBlock: nil,
+ TIPXDCXCancellationFeeBlock: nil,
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: nil,
+ LondonBlock: nil,
+ MergeBlock: nil,
+ ShanghaiBlock: nil,
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: nil,
+ TIPXDCXReceiverDisableBlock: nil,
+ Eip1559Block: nil,
+ CancunBlock: nil,
+ PragueBlock: nil,
+ OsakaBlock: nil,
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: new(EthashConfig),
+ XDPoS: nil,
}
// TestnetChainConfig contains the chain parameters to run a node on the Apothem testnet.
TestnetChainConfig = &ChainConfig{
- ChainID: big.NewInt(51),
- HomesteadBlock: big.NewInt(1),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(2),
- EIP155Block: big.NewInt(3),
- EIP158Block: big.NewInt(3),
- ByzantiumBlock: big.NewInt(4),
- ConstantinopleBlock: nil,
+ Name: "TestnetChainConfig",
+ ChainID: big.NewInt(51),
+ HomesteadBlock: big.NewInt(1),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(1),
+ EIP150Block: big.NewInt(2),
+ EIP155Block: big.NewInt(3),
+ EIP158Block: big.NewInt(3),
+ ByzantiumBlock: big.NewInt(4),
+ ConstantinopleBlock: nil,
+ PetersburgBlock: nil,
+ IstanbulBlock: nil,
+ TIPSigningBlock: big.NewInt(3000000),
+ TIPRandomizeBlock: big.NewInt(3464000),
+ TIPIncreaseMasternodesBlock: big.NewInt(5000000),
+ DenylistBlock: big.NewInt(23779191),
+ TIPNoHalvingMNRewardBlock: big.NewInt(23779191),
+ TIPXDCXBlock: big.NewInt(23779191),
+ TIPXDCXLendingBlock: big.NewInt(23779191),
+ TIPXDCXCancellationFeeBlock: big.NewInt(23779191),
+ TIPTRC21FeeBlock: big.NewInt(23779191),
+ Gas50xBlock: big.NewInt(56828700),
+ BerlinBlock: big.NewInt(61290000),
+ LondonBlock: big.NewInt(61290000),
+ MergeBlock: big.NewInt(61290000),
+ ShanghaiBlock: big.NewInt(61290000),
+ TIPXDCXMinerDisableBlock: big.NewInt(61290000),
+ TIPXDCXReceiverDisableBlock: big.NewInt(66825000),
+ Eip1559Block: big.NewInt(71550000),
+ CancunBlock: big.NewInt(71551800),
+ PragueBlock: nil,
+ OsakaBlock: nil,
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
+ XDCXListingSMC: common.HexToAddress("0x14B2Bf043b9c31827A472CE4F94294fE9a6277e0"),
+ RelayerRegistrationSMC: common.HexToAddress("0xA1996F69f47ba14Cb7f661010A7C31974277958c"),
+ LendingRegistrationSMC: common.HexToAddress("0x28d7fC2Cf5c18203aaCD7459EFC6Af0643C97bE8"),
+ Clique: nil,
+ Ethash: nil,
XDPoS: &XDPoSConfig{
Period: 2,
Epoch: 900,
@@ -260,9 +422,10 @@ var (
RewardCheckpoint: 900,
Gap: 450,
FoundationWalletAddr: common.HexToAddress("xdc746249c61f5832c5eed53172776b460491bdcd5c"),
+ MaxMasternodesV2: 15,
V2: &V2{
- SwitchEpoch: common.TestnetConstant.TIPV2SwitchBlock.Uint64() / 900,
- SwitchBlock: common.TestnetConstant.TIPV2SwitchBlock,
+ SwitchEpoch: TestnetV2SwitchBlock / 900,
+ SwitchBlock: big.NewInt(int64(TestnetV2SwitchBlock)),
CurrentConfig: TestnetV2Configs[0],
AllConfigs: TestnetV2Configs,
},
@@ -271,12 +434,49 @@ var (
// DevnetChainConfig contains the chain parameters to run a node on the devnet.
DevnetChainConfig = &ChainConfig{
- ChainID: big.NewInt(5551),
- HomesteadBlock: big.NewInt(0),
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
+ Name: "DevnetChainConfig",
+ ChainID: big.NewInt(5551),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: nil,
+ PetersburgBlock: nil,
+ IstanbulBlock: nil,
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(0),
+ TIPXDCXMinerDisableBlock: big.NewInt(0),
+ TIPXDCXReceiverDisableBlock: big.NewInt(0),
+ Eip1559Block: big.NewInt(250000),
+ CancunBlock: big.NewInt(250000),
+ PragueBlock: big.NewInt(5000000),
+ OsakaBlock: nil,
+ DynamicGasLimitBlock: big.NewInt(5000000),
+ TIPUpgradeRewardBlock: big.NewInt(5000000),
+ TIPUpgradePenaltyBlock: big.NewInt(5000000),
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: nil,
XDPoS: &XDPoSConfig{
Period: 2,
Epoch: 900,
@@ -284,39 +484,113 @@ var (
RewardCheckpoint: 900,
Gap: 450,
FoundationWalletAddr: common.HexToAddress("0x4f288181b1d1aa599c6d7629f1168d46d5f96338"),
+ MaxMasternodesV2: 108,
V2: &V2{
- SwitchEpoch: common.DevnetConstant.TIPV2SwitchBlock.Uint64() / 900,
- SwitchBlock: common.DevnetConstant.TIPV2SwitchBlock,
+ SwitchEpoch: DevnetV2SwitchBlock / 900,
+ SwitchBlock: big.NewInt(int64(DevnetV2SwitchBlock)),
CurrentConfig: DevnetV2Configs[0],
AllConfigs: DevnetV2Configs,
},
},
}
+ // LocalnetChainConfig contains the chain parameters to run a node on the local network.
+ LocalnetChainConfig = &ChainConfig{
+ Name: "LocalnetChainConfig",
+ ChainID: big.NewInt(5151),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: nil,
+ PetersburgBlock: nil,
+ IstanbulBlock: nil,
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(0),
+ TIPXDCXMinerDisableBlock: big.NewInt(0),
+ TIPXDCXReceiverDisableBlock: big.NewInt(0),
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: nil,
+ OsakaBlock: nil,
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: nil,
+ XDPoS: &XDPoSConfig{
+ MaxMasternodesV2: 108,
+ },
+ }
+
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Ethash consensus.
AllEthashProtocolChanges = &ChainConfig{
- ChainID: big.NewInt(1337),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(0),
- BerlinBlock: big.NewInt(0),
- LondonBlock: big.NewInt(0),
- ShanghaiBlock: big.NewInt(0),
- Eip1559Block: nil,
- CancunBlock: nil,
- PragueBlock: nil,
- OsakaBlock: nil,
- Ethash: new(EthashConfig),
- Clique: nil,
- XDPoS: nil,
+ Name: "AllEthashProtocolChanges",
+ ChainID: big.NewInt(1337),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: nil,
+ TIPXDCXReceiverDisableBlock: nil,
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ OsakaBlock: big.NewInt(0),
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: new(EthashConfig),
+ XDPoS: nil,
}
// AllDevChainProtocolChanges contains every protocol change (EIPs) introduced
@@ -325,32 +599,56 @@ var (
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllDevChainProtocolChanges = &ChainConfig{
- ChainID: big.NewInt(1337),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(0),
- BerlinBlock: big.NewInt(0),
- LondonBlock: big.NewInt(0),
- ShanghaiBlock: big.NewInt(0),
- Eip1559Block: big.NewInt(0),
- CancunBlock: big.NewInt(0),
- PragueBlock: big.NewInt(0),
- OsakaBlock: big.NewInt(0),
- Ethash: nil,
- Clique: nil,
+ Name: "AllDevChainProtocolChanges",
+ ChainID: big.NewInt(1337),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: nil,
+ TIPXDCXReceiverDisableBlock: nil,
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ OsakaBlock: big.NewInt(0),
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: nil,
XDPoS: &XDPoSConfig{
Epoch: 900,
Gap: 450,
SkipV1Validation: true,
FoundationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"),
Reward: 250,
+ MaxMasternodesV2: 108,
V2: &V2{
SwitchEpoch: 1,
SwitchBlock: big.NewInt(900),
@@ -363,48 +661,104 @@ var (
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus.
AllCliqueProtocolChanges = &ChainConfig{
- ChainID: big.NewInt(1337),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(0),
- BerlinBlock: big.NewInt(0),
- LondonBlock: big.NewInt(0),
- ShanghaiBlock: big.NewInt(0),
- Eip1559Block: big.NewInt(0),
- CancunBlock: nil,
- PragueBlock: nil,
- OsakaBlock: nil,
- Ethash: nil,
- Clique: &CliqueConfig{Period: 0, Epoch: 900},
- XDPoS: nil,
+ Name: "AllCliqueProtocolChanges",
+ ChainID: big.NewInt(1337),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: nil,
+ TIPXDCXReceiverDisableBlock: nil,
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ OsakaBlock: big.NewInt(0),
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: &CliqueConfig{Period: 0, Epoch: 900},
+ Ethash: nil,
+ XDPoS: nil,
}
// XDPoS config with v2 engine after block 901
TestXDPoSMockChainConfig = &ChainConfig{
- ChainID: big.NewInt(1337),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- Ethash: new(EthashConfig),
- Clique: nil,
+ Name: "TestXDPoSMockChainConfig",
+ ChainID: big.NewInt(1337),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: nil,
+ TIPXDCXReceiverDisableBlock: nil,
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ OsakaBlock: big.NewInt(0),
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: new(EthashConfig),
XDPoS: &XDPoSConfig{
Epoch: 900,
Gap: 450,
SkipV1Validation: true,
FoundationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"),
Reward: 250,
+ MaxMasternodesV2: 108,
V2: &V2{
SwitchEpoch: 1,
SwitchBlock: big.NewInt(900),
@@ -417,54 +771,101 @@ var (
// TestChainConfig contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers for testing purposes.
TestChainConfig = &ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(0),
- BerlinBlock: big.NewInt(0),
- LondonBlock: big.NewInt(0),
- ShanghaiBlock: big.NewInt(0),
- Eip1559Block: nil,
- CancunBlock: nil,
- PragueBlock: nil,
- OsakaBlock: nil,
- Ethash: new(EthashConfig),
- Clique: nil,
- XDPoS: nil,
+ Name: "TestChainConfig",
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: nil,
+ TIPXDCXReceiverDisableBlock: nil,
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ OsakaBlock: big.NewInt(0),
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: new(EthashConfig),
+ XDPoS: nil,
}
// MergedTestChainConfig contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers for testing purposes.
MergedTestChainConfig = &ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: false,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(0),
- BerlinBlock: big.NewInt(0),
- LondonBlock: big.NewInt(0),
- ShanghaiBlock: big.NewInt(0),
- Eip1559Block: big.NewInt(0),
- CancunBlock: big.NewInt(0),
- PragueBlock: big.NewInt(0),
- OsakaBlock: big.NewInt(0),
- Ethash: new(EthashConfig),
- Clique: nil,
- XDPoS: nil,
+ Name: "MergedTestChainConfig",
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ TIP2019Block: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ TIPSigningBlock: big.NewInt(0),
+ TIPRandomizeBlock: big.NewInt(0),
+ TIPIncreaseMasternodesBlock: big.NewInt(0),
+ DenylistBlock: big.NewInt(0),
+ TIPNoHalvingMNRewardBlock: big.NewInt(0),
+ TIPXDCXBlock: big.NewInt(0),
+ TIPXDCXLendingBlock: big.NewInt(0),
+ TIPXDCXCancellationFeeBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ MergeBlock: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ Gas50xBlock: big.NewInt(80370000),
+ TIPXDCXMinerDisableBlock: nil,
+ TIPXDCXReceiverDisableBlock: nil,
+ Eip1559Block: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ OsakaBlock: big.NewInt(0),
+ DynamicGasLimitBlock: nil,
+ TIPUpgradeRewardBlock: nil,
+ TIPUpgradePenaltyBlock: nil,
+ TIPEpochHalvingBlock: nil,
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Clique: nil,
+ Ethash: new(EthashConfig),
+ XDPoS: nil,
}
+
TestRules = TestChainConfig.Rules(new(big.Int))
)
@@ -500,12 +901,36 @@ type ChainConfig struct {
PragueBlock *big.Int `json:"pragueBlock,omitempty"`
OsakaBlock *big.Int `json:"osakaBlock,omitempty"`
- DynamicGasLimitBlock *big.Int `json:"dynamicGasLimitBlock,omitempty"` // Dynamic gas limit adjustment algorithm activation block (nil = no fork)
+ TIP2019Block *big.Int `json:"tip2019Block,omitempty"`
+ TIPSigningBlock *big.Int `json:"tipSigningBlock,omitempty"`
+ TIPRandomizeBlock *big.Int `json:"tipRandomizeBlock,omitempty"`
+ TIPIncreaseMasternodesBlock *big.Int `json:"tipIncreaseMasternodesBlock,omitempty"`
+ DenylistBlock *big.Int `json:"denylistBlock,omitempty"`
+ TIPNoHalvingMNRewardBlock *big.Int `json:"tipNoHalvingMNRewardBlock,omitempty"`
+ TIPXDCXBlock *big.Int `json:"tipXDCXBlock,omitempty"`
+ TIPXDCXLendingBlock *big.Int `json:"tipXDCXLendingBlock,omitempty"`
+ TIPXDCXCancellationFeeBlock *big.Int `json:"tipXDCXCancellationFeeBlock,omitempty"`
+ TIPTRC21FeeBlock *big.Int `json:"tipTRC21FeeBlock,omitempty"`
+ Gas50xBlock *big.Int `json:"gas50xBlock,omitempty"`
+ TIPXDCXMinerDisableBlock *big.Int `json:"tipXDCXMinerDisableBlock,omitempty"`
+ TIPXDCXReceiverDisableBlock *big.Int `json:"tipXDCXReceiverDisableBlock,omitempty"`
+ DynamicGasLimitBlock *big.Int `json:"dynamicGasLimitBlock,omitempty"`
+ TIPUpgradeRewardBlock *big.Int `json:"tipUpgradeRewardBlock,omitempty"`
+ TIPUpgradePenaltyBlock *big.Int `json:"tipUpgradePenaltyBlock,omitempty"`
+ TIPEpochHalvingBlock *big.Int `json:"tipEpochHalvingBlock,omitempty"`
+ TRC21IssuerSMC common.Address `json:"trc21IssuerSMC,omitempty"`
+ XDCXListingSMC common.Address `json:"xdcxListingSMC,omitempty"`
+ RelayerRegistrationSMC common.Address `json:"relayerRegistrationSMC,omitempty"`
+ LendingRegistrationSMC common.Address `json:"lendingRegistrationSMC,omitempty"`
// Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"`
Clique *CliqueConfig `json:"clique,omitempty"`
XDPoS *XDPoSConfig `json:"XDPoS,omitempty"`
+
+ Name string `json:"-"`
+ jsonPresence map[string]struct{} `json:"-"`
+ jsonPresenceTracked bool `json:"-"`
}
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
@@ -535,19 +960,49 @@ type XDPoSConfig struct {
RewardCheckpoint uint64 `json:"rewardCheckpoint"` // Checkpoint block for calculate rewards.
Gap uint64 `json:"gap"` // Gap time preparing for the next epoch
FoundationWalletAddr common.Address `json:"foundationWalletAddr"` // Foundation Address Wallet
+ MaxMasternodesV2 int `json:"maxMasternodesV2"` // Last v1 masternodes after TIPIncrease
SkipV1Validation bool //Skip Block Validation for testing purpose, V1 consensus only
V2 *V2 `json:"v2"`
+
+ jsonPresence map[string]struct{} `json:"-"`
+ jsonPresenceTracked bool `json:"-"`
+}
+
+// UnmarshalJSON captures field presence so strict missing-field backfill can
+// distinguish omitted keys from explicit zero-values.
+func (c *ChainConfig) UnmarshalJSON(data []byte) error {
+ type chainConfigAlias ChainConfig
+ var raw map[string]json.RawMessage
+ if err := json.Unmarshal(data, &raw); err != nil {
+ return err
+ }
+ var decoded chainConfigAlias
+ if err := json.Unmarshal(data, &decoded); err != nil {
+ return err
+ }
+ *c = ChainConfig(decoded)
+ c.jsonPresenceTracked = true
+ c.jsonPresence = make(map[string]struct{}, len(raw))
+ for key := range raw {
+ c.jsonPresence[key] = struct{}{}
+ }
+ return nil
}
// UnmarshalJSON supports both the current and legacy typo-ed JSON key for
// foundation wallet address to keep old on-disk chain configs compatible.
func (c *XDPoSConfig) UnmarshalJSON(data []byte) error {
+ var raw map[string]json.RawMessage
+ if err := json.Unmarshal(data, &raw); err != nil {
+ return err
+ }
type xdpJSON struct {
Period uint64 `json:"period"`
Epoch uint64 `json:"epoch"`
Reward uint64 `json:"reward"`
RewardCheckpoint uint64 `json:"rewardCheckpoint"`
Gap uint64 `json:"gap"`
+ MaxMasternodesV2 int `json:"maxMasternodesV2"`
FoundationWalletAddr common.Address `json:"foundationWalletAddr"`
LegacyFoudationWalletAddr common.Address `json:"foudationWalletAddr"`
SkipV1Validation bool `json:"SkipV1Validation"`
@@ -563,12 +1018,18 @@ func (c *XDPoSConfig) UnmarshalJSON(data []byte) error {
c.Reward = decoded.Reward
c.RewardCheckpoint = decoded.RewardCheckpoint
c.Gap = decoded.Gap
+ c.MaxMasternodesV2 = decoded.MaxMasternodesV2
c.FoundationWalletAddr = decoded.FoundationWalletAddr
if c.FoundationWalletAddr == (common.Address{}) && decoded.LegacyFoudationWalletAddr != (common.Address{}) {
c.FoundationWalletAddr = decoded.LegacyFoudationWalletAddr
}
c.SkipV1Validation = decoded.SkipV1Validation
c.V2 = decoded.V2
+ c.jsonPresenceTracked = true
+ c.jsonPresence = make(map[string]struct{}, len(raw))
+ for key := range raw {
+ c.jsonPresence[key] = struct{}{}
+ }
return nil
}
@@ -580,7 +1041,7 @@ type V2 struct {
SwitchBlock *big.Int `json:"switchBlock"`
CurrentConfig *V2Config `json:"config"`
AllConfigs map[uint64]*V2Config `json:"allConfigs"`
- configIndex []uint64 //list of switch block of configs
+ configIndex []uint64 // list of switch block of configs
}
type V2Config struct {
@@ -609,6 +1070,268 @@ type ExpTimeoutConfig struct {
MaxExponent uint8 `json:"maxExponent"` // max exponent in base^exponent
}
+// Clone returns an independent copy of the v2 config.
+func (c *V2Config) Clone() *V2Config {
+ if c == nil {
+ return nil
+ }
+ clone := *c
+ return &clone
+}
+
+// Clone returns a read-locked deep copy of the V2 state.
+func (v2 *V2) Clone() *V2 {
+ if v2 == nil {
+ return nil
+ }
+ v2.lock.RLock()
+ defer v2.lock.RUnlock()
+
+ clone := &V2{
+ SwitchEpoch: v2.SwitchEpoch,
+ SwitchBlock: common.CloneBigInt(v2.SwitchBlock),
+ }
+ if v2.CurrentConfig != nil {
+ clone.CurrentConfig = v2.CurrentConfig.Clone()
+ }
+ if v2.AllConfigs != nil {
+ clone.AllConfigs = make(map[uint64]*V2Config, len(v2.AllConfigs))
+ for key, cfg := range v2.AllConfigs {
+ clone.AllConfigs[key] = cfg.Clone()
+ }
+ }
+ if v2.configIndex != nil {
+ clone.configIndex = append([]uint64(nil), v2.configIndex...)
+ }
+ return clone
+}
+
+// Clone returns an independent copy of the XDPoS config.
+func (c *XDPoSConfig) Clone() *XDPoSConfig {
+ if c == nil {
+ return nil
+ }
+ clone := *c
+ clone.V2 = c.V2.Clone()
+ if c.jsonPresence != nil {
+ clone.jsonPresence = make(map[string]struct{}, len(c.jsonPresence))
+ for key := range c.jsonPresence {
+ clone.jsonPresence[key] = struct{}{}
+ }
+ }
+ return &clone
+}
+
+// Clone returns a deep copy of the chain config and nested consensus configs.
+func (c *ChainConfig) Clone() *ChainConfig {
+ if c == nil {
+ return nil
+ }
+ clone := *c
+ clone.ChainID = common.CloneBigInt(c.ChainID)
+ clone.HomesteadBlock = common.CloneBigInt(c.HomesteadBlock)
+ clone.TIP2019Block = common.CloneBigInt(c.TIP2019Block)
+ clone.DAOForkBlock = common.CloneBigInt(c.DAOForkBlock)
+ clone.EIP150Block = common.CloneBigInt(c.EIP150Block)
+ clone.EIP155Block = common.CloneBigInt(c.EIP155Block)
+ clone.EIP158Block = common.CloneBigInt(c.EIP158Block)
+ clone.ByzantiumBlock = common.CloneBigInt(c.ByzantiumBlock)
+ clone.ConstantinopleBlock = common.CloneBigInt(c.ConstantinopleBlock)
+ clone.PetersburgBlock = common.CloneBigInt(c.PetersburgBlock)
+ clone.IstanbulBlock = common.CloneBigInt(c.IstanbulBlock)
+ clone.TIPSigningBlock = common.CloneBigInt(c.TIPSigningBlock)
+ clone.TIPRandomizeBlock = common.CloneBigInt(c.TIPRandomizeBlock)
+ clone.TIPIncreaseMasternodesBlock = common.CloneBigInt(c.TIPIncreaseMasternodesBlock)
+ clone.DenylistBlock = common.CloneBigInt(c.DenylistBlock)
+ clone.TIPNoHalvingMNRewardBlock = common.CloneBigInt(c.TIPNoHalvingMNRewardBlock)
+ clone.TIPXDCXBlock = common.CloneBigInt(c.TIPXDCXBlock)
+ clone.TIPXDCXLendingBlock = common.CloneBigInt(c.TIPXDCXLendingBlock)
+ clone.TIPXDCXCancellationFeeBlock = common.CloneBigInt(c.TIPXDCXCancellationFeeBlock)
+ clone.TIPTRC21FeeBlock = common.CloneBigInt(c.TIPTRC21FeeBlock)
+ clone.BerlinBlock = common.CloneBigInt(c.BerlinBlock)
+ clone.LondonBlock = common.CloneBigInt(c.LondonBlock)
+ clone.MergeBlock = common.CloneBigInt(c.MergeBlock)
+ clone.ShanghaiBlock = common.CloneBigInt(c.ShanghaiBlock)
+ clone.Gas50xBlock = common.CloneBigInt(c.Gas50xBlock)
+ clone.TIPXDCXMinerDisableBlock = common.CloneBigInt(c.TIPXDCXMinerDisableBlock)
+ clone.TIPXDCXReceiverDisableBlock = common.CloneBigInt(c.TIPXDCXReceiverDisableBlock)
+ clone.Eip1559Block = common.CloneBigInt(c.Eip1559Block)
+ clone.CancunBlock = common.CloneBigInt(c.CancunBlock)
+ clone.PragueBlock = common.CloneBigInt(c.PragueBlock)
+ clone.OsakaBlock = common.CloneBigInt(c.OsakaBlock)
+ clone.DynamicGasLimitBlock = common.CloneBigInt(c.DynamicGasLimitBlock)
+ clone.TIPUpgradeRewardBlock = common.CloneBigInt(c.TIPUpgradeRewardBlock)
+ clone.TIPUpgradePenaltyBlock = common.CloneBigInt(c.TIPUpgradePenaltyBlock)
+ clone.TIPEpochHalvingBlock = common.CloneBigInt(c.TIPEpochHalvingBlock)
+ clone.TRC21IssuerSMC = c.TRC21IssuerSMC
+ clone.XDCXListingSMC = c.XDCXListingSMC
+ clone.RelayerRegistrationSMC = c.RelayerRegistrationSMC
+ clone.LendingRegistrationSMC = c.LendingRegistrationSMC
+ if c.Clique != nil {
+ clique := *c.Clique
+ clone.Clique = &clique
+ }
+ if c.Ethash != nil {
+ clone.Ethash = new(EthashConfig)
+ }
+ clone.XDPoS = c.XDPoS.Clone()
+ if c.jsonPresence != nil {
+ clone.jsonPresence = make(map[string]struct{}, len(c.jsonPresence))
+ for key := range c.jsonPresence {
+ clone.jsonPresence[key] = struct{}{}
+ }
+ }
+ return &clone
+}
+
+func GetBuiltInChainConfigByHash(ghash common.Hash) *ChainConfig {
+ switch ghash {
+ case MainnetGenesisHash:
+ return XDCMainnetChainConfig
+ case TestnetGenesisHash:
+ return TestnetChainConfig
+ case DevnetGenesisHash:
+ return DevnetChainConfig
+ default:
+ return nil
+ }
+}
+
+func isBuiltInTestNetwork(chainID *big.Int) bool {
+ switch chainID.Uint64() {
+ case TestnetChainConfig.ChainID.Uint64():
+ return true
+ case 1: // MainnetChainConfig, TestChainConfig, MergedTestChainConfig
+ return true
+ case 1337: // AllEthashProtocolChanges, AllDevChainProtocolChanges, AllCliqueProtocolChanges, TestXDPoSMockChainConfig
+ return true
+ default:
+ return false
+ }
+}
+
+// CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough
+// to guarantee that forks can be implemented in a different order than on official networks
+func (c *ChainConfig) CheckConfigForkOrder() error {
+ if c.ChainID == nil {
+ return fmt.Errorf("invalid chain config: %w %s", ErrMissingForkSwitch, "ChainID")
+ }
+ if c.TIPTRC21FeeBlock == nil {
+ return fmt.Errorf("invalid chain config: %w %s", ErrMissingForkSwitch, "TIPTRC21FeeBlock")
+ }
+ if c.Gas50xBlock != nil && c.Gas50xBlock.Cmp(c.TIPTRC21FeeBlock) < 0 {
+ return fmt.Errorf("invalid chain config: %w TIPTRC21FeeBlock %v > Gas50xBlock %v", ErrWrongForkSwitchOrder, c.TIPTRC21FeeBlock, c.Gas50xBlock)
+ }
+ if c.XDPoS == nil && c.Ethash == nil && c.Clique == nil && !isBuiltInTestNetwork(c.ChainID) {
+ return fmt.Errorf("invalid chain config: %w %s", ErrMissingForkSwitch, "XDPoS")
+ }
+ if c.XDPoS != nil {
+ if c.XDPoS.MaxMasternodesV2 == 0 {
+ return fmt.Errorf("invalid chain config: %w %s", ErrMissingForkSwitch, "XDPoS.MaxMasternodesV2")
+ }
+ }
+ return nil
+}
+
+func (c *ChainConfig) isJSONFieldMissing(key string, fallback bool) bool {
+ if c == nil {
+ return false
+ }
+ if !c.jsonPresenceTracked {
+ return fallback
+ }
+ _, ok := c.jsonPresence[key]
+ return !ok
+}
+
+// BackfillMissingFields copies missing fields from LocalnetChainConfig into c
+// using strict JSON-key presence when available. If presence metadata is
+// unavailable, pointer-nil/zero-value fallbacks are used for compatibility.
+func (c *ChainConfig) BackfillMissingFields() *ChainConfig {
+ if c == nil {
+ return c
+ }
+
+ dest := c.Clone()
+ src := LocalnetChainConfig
+
+ bigIntFields := []struct {
+ key string
+ dst **big.Int
+ src *big.Int
+ }{
+ {"chainId", &dest.ChainID, src.ChainID},
+ {"homesteadBlock", &dest.HomesteadBlock, src.HomesteadBlock},
+ {"daoForkBlock", &dest.DAOForkBlock, src.DAOForkBlock},
+ {"eip150Block", &dest.EIP150Block, src.EIP150Block},
+ {"eip155Block", &dest.EIP155Block, src.EIP155Block},
+ {"eip158Block", &dest.EIP158Block, src.EIP158Block},
+ {"byzantiumBlock", &dest.ByzantiumBlock, src.ByzantiumBlock},
+ {"constantinopleBlock", &dest.ConstantinopleBlock, src.ConstantinopleBlock},
+ {"petersburgBlock", &dest.PetersburgBlock, src.PetersburgBlock},
+ {"istanbulBlock", &dest.IstanbulBlock, src.IstanbulBlock},
+ {"tip2019Block", &dest.TIP2019Block, src.TIP2019Block},
+ {"tipSigningBlock", &dest.TIPSigningBlock, src.TIPSigningBlock},
+ {"tipRandomizeBlock", &dest.TIPRandomizeBlock, src.TIPRandomizeBlock},
+ {"tipIncreaseMasternodesBlock", &dest.TIPIncreaseMasternodesBlock, src.TIPIncreaseMasternodesBlock},
+ {"denylistBlock", &dest.DenylistBlock, src.DenylistBlock},
+ {"tipNoHalvingMNRewardBlock", &dest.TIPNoHalvingMNRewardBlock, src.TIPNoHalvingMNRewardBlock},
+ {"tipXDCXBlock", &dest.TIPXDCXBlock, src.TIPXDCXBlock},
+ {"tipXDCXLendingBlock", &dest.TIPXDCXLendingBlock, src.TIPXDCXLendingBlock},
+ {"tipXDCXCancellationFeeBlock", &dest.TIPXDCXCancellationFeeBlock, src.TIPXDCXCancellationFeeBlock},
+ {"tipTRC21FeeBlock", &dest.TIPTRC21FeeBlock, src.TIPTRC21FeeBlock},
+ {"gas50xBlock", &dest.Gas50xBlock, src.Gas50xBlock},
+ {"berlinBlock", &dest.BerlinBlock, src.BerlinBlock},
+ {"londonBlock", &dest.LondonBlock, src.LondonBlock},
+ {"mergeBlock", &dest.MergeBlock, src.MergeBlock},
+ {"shanghaiBlock", &dest.ShanghaiBlock, src.ShanghaiBlock},
+ {"tipXDCXMinerDisableBlock", &dest.TIPXDCXMinerDisableBlock, src.TIPXDCXMinerDisableBlock},
+ {"tipXDCXReceiverDisableBlock", &dest.TIPXDCXReceiverDisableBlock, src.TIPXDCXReceiverDisableBlock},
+ {"eip1559Block", &dest.Eip1559Block, src.Eip1559Block},
+ {"cancunBlock", &dest.CancunBlock, src.CancunBlock},
+ {"pragueBlock", &dest.PragueBlock, src.PragueBlock},
+ {"osakaBlock", &dest.OsakaBlock, src.OsakaBlock},
+ {"dynamicGasLimitBlock", &dest.DynamicGasLimitBlock, src.DynamicGasLimitBlock},
+ {"tipUpgradeRewardBlock", &dest.TIPUpgradeRewardBlock, src.TIPUpgradeRewardBlock},
+ {"tipUpgradePenaltyBlock", &dest.TIPUpgradePenaltyBlock, src.TIPUpgradePenaltyBlock},
+ {"tipEpochHalvingBlock", &dest.TIPEpochHalvingBlock, src.TIPEpochHalvingBlock},
+ }
+
+ addressFields := []struct {
+ key string
+ dst *common.Address
+ src common.Address
+ }{
+ {"trc21IssuerSMC", &dest.TRC21IssuerSMC, src.TRC21IssuerSMC},
+ {"xdcxListingSMC", &dest.XDCXListingSMC, src.XDCXListingSMC},
+ {"relayerRegistrationSMC", &dest.RelayerRegistrationSMC, src.RelayerRegistrationSMC},
+ {"lendingRegistrationSMC", &dest.LendingRegistrationSMC, src.LendingRegistrationSMC},
+ }
+
+ for _, field := range bigIntFields {
+ if dest.isJSONFieldMissing(field.key, *field.dst == nil) {
+ log.Info("Backfilled missing field", "field", field.key, "old", *field.dst, "new", field.src)
+ *field.dst = common.CloneBigInt(field.src)
+ }
+ }
+
+ for _, field := range addressFields {
+ if dest.isJSONFieldMissing(field.key, *field.dst == (common.Address{})) {
+ log.Info("Backfilled missing field", "field", field.key, "old", field.dst.Hex(), "new", field.src.Hex())
+ *field.dst = field.src
+ }
+ }
+
+ if dest.XDPoS == nil {
+ log.Warn("XDPoS in source chain config is nil")
+ } else if dest.XDPoS.MaxMasternodesV2 == 0 {
+ log.Info("Backfilled missing field", "field", "XDPoS.MaxMasternodesV2", "old", 0, "new", src.XDPoS.MaxMasternodesV2)
+ dest.XDPoS.MaxMasternodesV2 = src.XDPoS.MaxMasternodesV2
+ }
+
+ return dest
+}
+
func XDPoSConfigEqual(a, b *XDPoSConfig) bool {
if a == nil || b == nil {
if a != b {
@@ -641,6 +1364,10 @@ func XDPoSConfigEqual(a, b *XDPoSConfig) bool {
log.Warn("[XDPoSConfigEqual] FoundationWalletAddr mismatch", "a.FoundationWalletAddr", a.FoundationWalletAddr.Hex(), "b.FoundationWalletAddr", b.FoundationWalletAddr.Hex())
return false
}
+ if a.MaxMasternodesV2 != b.MaxMasternodesV2 {
+ log.Warn("[XDPoSConfigEqual] MaxMasternodesV2 mismatch", "a.MaxMasternodesV2", a.MaxMasternodesV2, "b.MaxMasternodesV2", b.MaxMasternodesV2)
+ return false
+ }
if a.SkipV1Validation != b.SkipV1Validation {
log.Warn("[XDPoSConfigEqual] SkipV1Validation mismatch", "a.SkipV1Validation", a.SkipV1Validation, "b.SkipV1Validation", b.SkipV1Validation)
return false
@@ -699,7 +1426,7 @@ func (c *XDPoSConfig) String() string {
return "XDPoSConfig: "
}
- return fmt.Sprintf("XDPoSConfig{Period: %v, Epoch: %v, Reward: %v, RewardCheckpoint: %v, Gap: %v, FoundationWalletAddr: %v, SkipV1Validation: %v, V2: %s}", c.Period, c.Epoch, c.Reward, c.RewardCheckpoint, c.Gap, c.FoundationWalletAddr.String0x(), c.SkipV1Validation, c.V2.String())
+ return fmt.Sprintf("XDPoSConfig{Period: %v, Epoch: %v, Reward: %v, RewardCheckpoint: %v, Gap: %v, MaxMasternodesV2: %v, FoundationWalletAddr: %v, SkipV1Validation: %v, V2: %s}", c.Period, c.Epoch, c.Reward, c.RewardCheckpoint, c.Gap, c.MaxMasternodesV2, c.FoundationWalletAddr.String0x(), c.SkipV1Validation, c.V2.String())
}
// Description returns a human-readable description of XDPoSConfig
@@ -716,6 +1443,7 @@ func (c *XDPoSConfig) Description(indent int) string {
banner += fmt.Sprintf("%s- Reward: %v\n", prefix, c.Reward)
banner += fmt.Sprintf("%s- RewardCheckpoint: %v\n", prefix, c.RewardCheckpoint)
banner += fmt.Sprintf("%s- Gap: %v\n", prefix, c.Gap)
+ banner += fmt.Sprintf("%s- MaxMasternodesV2: %v\n", prefix, c.MaxMasternodesV2)
banner += fmt.Sprintf("%s- FoundationWalletAddr: %v\n", prefix, c.FoundationWalletAddr.Hex())
banner += fmt.Sprintf("%s- SkipV1Validation: %v\n", prefix, c.SkipV1Validation)
banner += fmt.Sprintf("%s- %s", prefix, c.V2.Description(indent+2))
@@ -856,7 +1584,13 @@ func (v2 *V2) BuildConfigIndex() {
}
func (v2 *V2) ConfigIndex() []uint64 {
- return v2.configIndex
+ v2.lock.RLock()
+ defer v2.lock.RUnlock()
+
+ if v2.configIndex == nil {
+ return nil
+ }
+ return append([]uint64(nil), v2.configIndex...)
}
// String implements the fmt.Stringer interface, returning a string representation
@@ -866,55 +1600,128 @@ func (c *ChainConfig) String() string {
// Add block-based forks
if c.HomesteadBlock != nil {
- result += fmt.Sprintf(", HomesteadBlock: %v", c.HomesteadBlock)
+ result += fmt.Sprintf(", Homestead: %v", c.HomesteadBlock)
+ }
+ if c.TIP2019Block != nil {
+ result += fmt.Sprintf(", TIP2019: %v", c.TIP2019Block)
}
if c.DAOForkBlock != nil {
- result += fmt.Sprintf(", DAOForkBlock: %v", c.DAOForkBlock)
+ result += fmt.Sprintf(", DAOFork: %v", c.DAOForkBlock)
}
+ result += fmt.Sprintf(", DAOForkSupport: %v", c.DAOForkSupport)
if c.EIP150Block != nil {
- result += fmt.Sprintf(", EIP150Block: %v", c.EIP150Block)
+ result += fmt.Sprintf(", EIP150: %v", c.EIP150Block)
}
if c.EIP155Block != nil {
- result += fmt.Sprintf(", EIP155Block: %v", c.EIP155Block)
+ result += fmt.Sprintf(", EIP155: %v", c.EIP155Block)
}
if c.EIP158Block != nil {
- result += fmt.Sprintf(", EIP158Block: %v", c.EIP158Block)
+ result += fmt.Sprintf(", EIP158: %v", c.EIP158Block)
}
if c.ByzantiumBlock != nil {
- result += fmt.Sprintf(", ByzantiumBlock: %v", c.ByzantiumBlock)
+ result += fmt.Sprintf(", Byzantium: %v", c.ByzantiumBlock)
}
if c.ConstantinopleBlock != nil {
- result += fmt.Sprintf(", ConstantinopleBlock: %v", c.ConstantinopleBlock)
+ result += fmt.Sprintf(", Constantinople: %v", c.ConstantinopleBlock)
}
if c.PetersburgBlock != nil {
- result += fmt.Sprintf(", PetersburgBlock: %v", c.PetersburgBlock)
+ result += fmt.Sprintf(", Petersburg: %v", c.PetersburgBlock)
}
if c.IstanbulBlock != nil {
- result += fmt.Sprintf(", IstanbulBlock: %v", c.IstanbulBlock)
+ result += fmt.Sprintf(", Istanbul: %v", c.IstanbulBlock)
+ }
+ if c.TIPSigningBlock != nil {
+ result += fmt.Sprintf(", TIPSigning: %v", c.TIPSigningBlock)
+ }
+ if c.TIPRandomizeBlock != nil {
+ result += fmt.Sprintf(", TIPRandomize: %v", c.TIPRandomizeBlock)
+ }
+ if c.TIPIncreaseMasternodesBlock != nil {
+ result += fmt.Sprintf(", TIPIncreaseMasternodes: %v", c.TIPIncreaseMasternodesBlock)
+ }
+ if c.DenylistBlock != nil {
+ result += fmt.Sprintf(", Denylist: %v", c.DenylistBlock)
+ }
+ if c.TIPNoHalvingMNRewardBlock != nil {
+ result += fmt.Sprintf(", TIPNoHalvingMNReward: %v", c.TIPNoHalvingMNRewardBlock)
+ }
+ if c.TIPXDCXBlock != nil {
+ result += fmt.Sprintf(", TIPXDCX: %v", c.TIPXDCXBlock)
+ }
+ if c.TIPXDCXLendingBlock != nil {
+ result += fmt.Sprintf(", TIPXDCXLending: %v", c.TIPXDCXLendingBlock)
+ }
+ if c.TIPXDCXCancellationFeeBlock != nil {
+ result += fmt.Sprintf(", TIPXDCXCancellationFee: %v", c.TIPXDCXCancellationFeeBlock)
+ }
+ if c.TIPTRC21FeeBlock != nil {
+ result += fmt.Sprintf(", TIPTRC21Fee: %v", c.TIPTRC21FeeBlock)
}
if c.BerlinBlock != nil {
- result += fmt.Sprintf(", BerlinBlock: %v", c.BerlinBlock)
+ result += fmt.Sprintf(", Berlin: %v", c.BerlinBlock)
}
if c.LondonBlock != nil {
- result += fmt.Sprintf(", LondonBlock: %v", c.LondonBlock)
+ result += fmt.Sprintf(", London: %v", c.LondonBlock)
}
if c.MergeBlock != nil {
- result += fmt.Sprintf(", MergeBlock: %v", c.MergeBlock)
+ result += fmt.Sprintf(", Merge: %v", c.MergeBlock)
}
if c.ShanghaiBlock != nil {
- result += fmt.Sprintf(", ShanghaiBlock: %v", c.ShanghaiBlock)
+ result += fmt.Sprintf(", Shanghai: %v", c.ShanghaiBlock)
+ }
+ if c.Gas50xBlock != nil {
+ result += fmt.Sprintf(", Gas50x: %v", c.Gas50xBlock)
+ }
+ if c.TIPXDCXMinerDisableBlock != nil {
+ result += fmt.Sprintf(", TIPXDCXMinerDisable: %v", c.TIPXDCXMinerDisableBlock)
+ }
+ if c.TIPXDCXReceiverDisableBlock != nil {
+ result += fmt.Sprintf(", TIPXDCXReceiverDisable: %v", c.TIPXDCXReceiverDisableBlock)
+ }
+ if c.Eip1559Block != nil {
+ result += fmt.Sprintf(", Eip1559: %v", c.Eip1559Block)
}
if c.CancunBlock != nil {
- result += fmt.Sprintf(", CancunBlock: %v", c.CancunBlock)
+ result += fmt.Sprintf(", Cancun: %v", c.CancunBlock)
}
if c.PragueBlock != nil {
- result += fmt.Sprintf(", PragueBlock: %v", c.PragueBlock)
+ result += fmt.Sprintf(", Prague: %v", c.PragueBlock)
+ }
+ if c.OsakaBlock != nil {
+ result += fmt.Sprintf(", Osaka: %v", c.OsakaBlock)
}
if c.DynamicGasLimitBlock != nil {
- result += fmt.Sprintf(", DynamicGasLimitBlock: %v", c.DynamicGasLimitBlock)
+ result += fmt.Sprintf(", DynamicGasLimit: %v", c.DynamicGasLimitBlock)
+ }
+ if c.TIPUpgradeRewardBlock != nil {
+ result += fmt.Sprintf(", TIPUpgradeReward: %v", c.TIPUpgradeRewardBlock)
+ }
+ if c.TIPUpgradePenaltyBlock != nil {
+ result += fmt.Sprintf(", TIPUpgradePenalty: %v", c.TIPUpgradePenaltyBlock)
+ }
+ if c.TIPEpochHalvingBlock != nil {
+ result += fmt.Sprintf(", TIPEpochHalving: %v", c.TIPEpochHalvingBlock)
+ }
+ if c.TRC21IssuerSMC != (common.Address{}) {
+ result += fmt.Sprintf(", TRC21IssuerSMC: %s", c.TRC21IssuerSMC.Hex())
+ }
+ if c.XDCXListingSMC != (common.Address{}) {
+ result += fmt.Sprintf(", XDCXListingSMC: %s", c.XDCXListingSMC.Hex())
+ }
+ if c.RelayerRegistrationSMC != (common.Address{}) {
+ result += fmt.Sprintf(", RelayerRegistrationSMC: %s", c.RelayerRegistrationSMC.Hex())
+ }
+ if c.LendingRegistrationSMC != (common.Address{}) {
+ result += fmt.Sprintf(", LendingRegistrationSMC: %s", c.LendingRegistrationSMC.Hex())
+ }
+ if c.Ethash != nil {
+ result += fmt.Sprintf(", Ethash: %s", c.Ethash.String())
+ }
+ if c.Clique != nil {
+ result += fmt.Sprintf(", Clique: %s", c.Clique.String())
}
if c.XDPoS != nil {
- result += fmt.Sprintf(", %s", c.XDPoS.String())
+ result += fmt.Sprintf(", XDPoS: %s", c.XDPoS.String())
}
result += "}"
return result
@@ -932,79 +1739,46 @@ func (c *ChainConfig) Description() string {
default:
engine = "unknown"
}
- berlinBlock := common.BerlinBlock
- if c.BerlinBlock != nil {
- berlinBlock = c.BerlinBlock
- }
- londonBlock := common.LondonBlock
- if c.LondonBlock != nil {
- londonBlock = c.LondonBlock
- }
- mergeBlock := common.MergeBlock
- if c.MergeBlock != nil {
- mergeBlock = c.MergeBlock
- }
- shanghaiBlock := common.ShanghaiBlock
- if c.ShanghaiBlock != nil {
- shanghaiBlock = c.ShanghaiBlock
- }
- eip1559Block := common.Eip1559Block
- if c.Eip1559Block != nil {
- eip1559Block = c.Eip1559Block
- }
- cancunBlock := common.CancunBlock
- if c.CancunBlock != nil {
- cancunBlock = c.CancunBlock
- }
- pragueBlock := common.PragueBlock
- if c.PragueBlock != nil {
- pragueBlock = c.PragueBlock
- }
- osakaBlock := common.OsakaBlock
- if c.OsakaBlock != nil {
- osakaBlock = c.OsakaBlock
- }
- dynamicGasLimitBlock := common.DynamicGasLimitBlock
- if c.DynamicGasLimitBlock != nil {
- dynamicGasLimitBlock = c.DynamicGasLimitBlock
- }
-
var banner = "Chain configuration:\n"
banner += fmt.Sprintf(" - ChainID: %-8v\n", c.ChainID)
banner += fmt.Sprintf(" - Homestead: %-8v\n", c.HomesteadBlock)
banner += fmt.Sprintf(" - DAO Fork: %-8v\n", c.DAOForkBlock)
banner += fmt.Sprintf(" - DAO Support: %-8v\n", c.DAOForkSupport)
+ banner += fmt.Sprintf(" - TIP2019: %-8v\n", c.TIP2019Block)
banner += fmt.Sprintf(" - Tangerine Whistle (EIP 150): %-8v\n", c.EIP150Block)
banner += fmt.Sprintf(" - Spurious Dragon (EIP 155): %-8v\n", c.EIP155Block)
banner += fmt.Sprintf(" - Byzantium: %-8v\n", c.ByzantiumBlock)
banner += fmt.Sprintf(" - Constantinople: %-8v\n", c.ConstantinopleBlock)
banner += fmt.Sprintf(" - Petersburg: %-8v\n", c.PetersburgBlock)
banner += fmt.Sprintf(" - Istanbul: %-8v\n", c.IstanbulBlock)
- banner += fmt.Sprintf(" - TIP2019Block: %-8v\n", common.TIP2019Block)
- banner += fmt.Sprintf(" - TIPSigning: %-8v\n", common.TIPSigning)
- banner += fmt.Sprintf(" - TIPRandomize: %-8v\n", common.TIPRandomize)
- banner += fmt.Sprintf(" - TIPIncreaseMasternodes: %-8v\n", common.TIPIncreaseMasternodes)
- banner += fmt.Sprintf(" - DenylistHFNumber: %-8v\n", common.DenylistHFNumber)
- banner += fmt.Sprintf(" - TIPNoHalvingMNReward: %-8v\n", common.TIPNoHalvingMNReward)
- banner += fmt.Sprintf(" - TIPXDCX: %-8v\n", common.TIPXDCX)
- banner += fmt.Sprintf(" - TIPXDCXLending: %-8v\n", common.TIPXDCXLending)
- banner += fmt.Sprintf(" - TIPXDCXCancellationFee: %-8v\n", common.TIPXDCXCancellationFee)
- banner += fmt.Sprintf(" - TIPTRC21Fee: %-8v\n", common.TIPTRC21Fee)
- banner += fmt.Sprintf(" - Berlin: %-8v\n", berlinBlock)
- banner += fmt.Sprintf(" - London: %-8v\n", londonBlock)
- banner += fmt.Sprintf(" - Merge: %-8v\n", mergeBlock)
- banner += fmt.Sprintf(" - Shanghai: %-8v\n", shanghaiBlock)
- banner += fmt.Sprintf(" - BlockNumberGas50x: %-8v\n", common.BlockNumberGas50x)
- banner += fmt.Sprintf(" - TIPXDCXMinerDisable: %-8v\n", common.TIPXDCXMinerDisable)
- banner += fmt.Sprintf(" - TIPXDCXReceiverDisable: %-8v\n", common.TIPXDCXReceiverDisable)
- banner += fmt.Sprintf(" - Eip1559: %-8v\n", eip1559Block)
- banner += fmt.Sprintf(" - Cancun: %-8v\n", cancunBlock)
- banner += fmt.Sprintf(" - Prague: %-8v\n", pragueBlock)
- banner += fmt.Sprintf(" - Osaka: %-8v\n", osakaBlock)
- banner += fmt.Sprintf(" - DynamicGasLimitBlock: %-8v\n", dynamicGasLimitBlock)
- banner += fmt.Sprintf(" - TIPUpgradeReward: %-8v\n", common.TIPUpgradeReward)
- banner += fmt.Sprintf(" - TipUpgradePenalty: %-8v\n", common.TipUpgradePenalty)
- banner += fmt.Sprintf(" - TIPEpochHalving: %-8v\n", common.TIPEpochHalving)
+ banner += fmt.Sprintf(" - TIPSigning: %-8v\n", c.TIPSigningBlock)
+ banner += fmt.Sprintf(" - TIPRandomize: %-8v\n", c.TIPRandomizeBlock)
+ banner += fmt.Sprintf(" - TIPIncreaseMasternodes: %-8v\n", c.TIPIncreaseMasternodesBlock)
+ banner += fmt.Sprintf(" - Denylist: %-8v\n", c.DenylistBlock)
+ banner += fmt.Sprintf(" - TIPNoHalvingMNReward: %-8v\n", c.TIPNoHalvingMNRewardBlock)
+ banner += fmt.Sprintf(" - TIPXDCX: %-8v\n", c.TIPXDCXBlock)
+ banner += fmt.Sprintf(" - TIPXDCXLending: %-8v\n", c.TIPXDCXLendingBlock)
+ banner += fmt.Sprintf(" - TIPXDCXCancellationFee: %-8v\n", c.TIPXDCXCancellationFeeBlock)
+ banner += fmt.Sprintf(" - TIPTRC21Fee: %-8v\n", c.TIPTRC21FeeBlock)
+ banner += fmt.Sprintf(" - Berlin: %-8v\n", c.BerlinBlock)
+ banner += fmt.Sprintf(" - London: %-8v\n", c.LondonBlock)
+ banner += fmt.Sprintf(" - Merge: %-8v\n", c.MergeBlock)
+ banner += fmt.Sprintf(" - Shanghai: %-8v\n", c.ShanghaiBlock)
+ banner += fmt.Sprintf(" - Gas50x: %-8v\n", c.Gas50xBlock)
+ banner += fmt.Sprintf(" - TIPXDCXMinerDisable: %-8v\n", c.TIPXDCXMinerDisableBlock)
+ banner += fmt.Sprintf(" - TIPXDCXReceiverDisable: %-8v\n", c.TIPXDCXReceiverDisableBlock)
+ banner += fmt.Sprintf(" - Eip1559: %-8v\n", c.Eip1559Block)
+ banner += fmt.Sprintf(" - Cancun: %-8v\n", c.CancunBlock)
+ banner += fmt.Sprintf(" - Prague: %-8v\n", c.PragueBlock)
+ banner += fmt.Sprintf(" - Osaka: %-8v\n", c.OsakaBlock)
+ banner += fmt.Sprintf(" - DynamicGasLimit: %-8v\n", c.DynamicGasLimitBlock)
+ banner += fmt.Sprintf(" - TIPUpgradeReward: %-8v\n", c.TIPUpgradeRewardBlock)
+ banner += fmt.Sprintf(" - TIPUpgradePenalty: %-8v\n", c.TIPUpgradePenaltyBlock)
+ banner += fmt.Sprintf(" - TIPEpochHalving: %-8v\n", c.TIPEpochHalvingBlock)
+ banner += fmt.Sprintf(" - TRC21IssuerSMC: %-8s\n", c.TRC21IssuerSMC)
+ banner += fmt.Sprintf(" - XDCXListingSMC: %-8s\n", c.XDCXListingSMC)
+ banner += fmt.Sprintf(" - RelayerRegistrationSMC: %-8s\n", c.RelayerRegistrationSMC)
+ banner += fmt.Sprintf(" - LendingRegistrationSMC: %-8s\n", c.LendingRegistrationSMC)
banner += fmt.Sprintf(" - Engine: %v", engine)
return banner
}
@@ -1014,6 +1788,10 @@ func (c *ChainConfig) IsHomestead(num *big.Int) bool {
return isForked(c.HomesteadBlock, num)
}
+func (c *ChainConfig) IsTIP2019(num *big.Int) bool {
+ return isForked(c.TIP2019Block, num)
+}
+
// IsDAO returns whether num is either equal to the DAO fork block or greater.
func (c *ChainConfig) IsDAOFork(num *big.Int) bool {
return isForked(c.DAOForkBlock, num)
@@ -1039,121 +1817,132 @@ func (c *ChainConfig) IsConstantinople(num *big.Int) bool {
return isForked(c.ConstantinopleBlock, num)
}
-// IsPetersburg returns whether num is either
-// - equal to or greater than the PetersburgBlock fork block,
-// - OR is nil, and Constantinople is active
+// IsPetersburg returns whether num is either equal to the Petersburg fork block or greater.
func (c *ChainConfig) IsPetersburg(num *big.Int) bool {
- return isForked(common.TIPXDCXCancellationFee, num) || isForked(c.PetersburgBlock, num)
+ return isForked(c.TIPXDCXCancellationFeeBlock, num) || isForked(c.PetersburgBlock, num)
}
-// IsIstanbul returns whether num is either equal to the Istanbul fork block or greater.
+// IsIstanbul returns whether num is either equal to the TIPXDCXCancellationFeeBlock fork block or greater.
func (c *ChainConfig) IsIstanbul(num *big.Int) bool {
- return isForked(common.TIPXDCXCancellationFee, num) || isForked(c.IstanbulBlock, num)
+ return isForked(c.TIPXDCXCancellationFeeBlock, num) || isForked(c.IstanbulBlock, num)
+}
+
+// IsTIPTRC21Fee returns whether num is either equal to the TIPTRC21Fee fork block or greater.
+func (c *ChainConfig) IsTIPTRC21Fee(num *big.Int) bool {
+ return isForked(c.TIPTRC21FeeBlock, num)
+}
+
+func (c *ChainConfig) IsDenylist(num *big.Int) bool {
+ return isForked(c.DenylistBlock, num)
}
// IsBerlin returns whether num is either equal to the Berlin fork block or greater.
func (c *ChainConfig) IsBerlin(num *big.Int) bool {
- return isForked(common.BerlinBlock, num) || isForked(c.BerlinBlock, num)
+ return isForked(c.BerlinBlock, num)
}
// IsLondon returns whether num is either equal to the London fork block or greater.
func (c *ChainConfig) IsLondon(num *big.Int) bool {
- return isForked(common.LondonBlock, num) || isForked(c.LondonBlock, num)
+ return isForked(c.LondonBlock, num)
}
// IsMerge returns whether num is either equal to the Merge fork block or greater.
// Different from Geth which uses `block.difficulty != nil`
func (c *ChainConfig) IsMerge(num *big.Int) bool {
- return isForked(common.MergeBlock, num) || isForked(c.MergeBlock, num)
+ return isForked(c.MergeBlock, num)
}
// IsShanghai returns whether num is either equal to the Shanghai fork block or greater.
func (c *ChainConfig) IsShanghai(num *big.Int) bool {
- return isForked(common.ShanghaiBlock, num) || isForked(c.ShanghaiBlock, num)
+ return isForked(c.ShanghaiBlock, num)
+}
+
+// IsGas50x returns whether num is either equal to the Gas50x fork block or greater.
+func (c *ChainConfig) IsGas50x(num *big.Int) bool {
+ return isForked(c.Gas50xBlock, num)
}
// IsEIP1559 returns whether num is either equal to the EIP1559 fork block or greater.
func (c *ChainConfig) IsEIP1559(num *big.Int) bool {
- return isForked(common.Eip1559Block, num) || isForked(c.Eip1559Block, num)
+ return isForked(c.Eip1559Block, num)
}
// IsCancun returns whether num is either equal to the Cancun fork block or greater.
func (c *ChainConfig) IsCancun(num *big.Int) bool {
- return isForked(common.CancunBlock, num) || isForked(c.CancunBlock, num)
+ return isForked(c.CancunBlock, num)
}
// IsPrague returns whether num is either equal to the Prague fork block or greater.
func (c *ChainConfig) IsPrague(num *big.Int) bool {
- return isForked(common.PragueBlock, num) || isForked(c.PragueBlock, num)
+ return isForked(c.PragueBlock, num)
}
// IsOsaka returns whether num is either equal to the Osaka fork block or greater.
func (c *ChainConfig) IsOsaka(num *big.Int) bool {
- return isForked(common.OsakaBlock, num) || isForked(c.OsakaBlock, num)
-}
-
-// IsDynamicGasLimitBlock returns whether num is either equal to the DynamicGasLimitBlock fork block or greater.
-func (c *ChainConfig) IsDynamicGasLimitBlock(num *big.Int) bool {
- return isForked(common.DynamicGasLimitBlock, num) || isForked(c.DynamicGasLimitBlock, num)
+ return isForked(c.OsakaBlock, num)
}
-func (c *ChainConfig) IsTIP2019(num *big.Int) bool {
- return isForked(common.TIP2019Block, num)
+// IsDynamicGasLimit returns whether num is either equal to the DynamicGasLimit fork block or greater.
+func (c *ChainConfig) IsDynamicGasLimit(num *big.Int) bool {
+ return isForked(c.DynamicGasLimitBlock, num)
}
func (c *ChainConfig) IsTIPSigning(num *big.Int) bool {
- return isForked(common.TIPSigning, num)
+ return isForked(c.TIPSigningBlock, num)
}
func (c *ChainConfig) IsTIPRandomize(num *big.Int) bool {
- return isForked(common.TIPRandomize, num)
+ return isForked(c.TIPRandomizeBlock, num)
}
// IsTIPIncreaseMasternodes using for increase masternodes from 18 to 40
-
-// Time update: 23-07-2019
func (c *ChainConfig) IsTIPIncreaseMasternodes(num *big.Int) bool {
- return isForked(common.TIPIncreaseMasternodes, num)
+ return isForked(c.TIPIncreaseMasternodesBlock, num)
}
func (c *ChainConfig) IsTIPNoHalvingMNReward(num *big.Int) bool {
- return isForked(common.TIPNoHalvingMNReward, num)
+ return isForked(c.TIPNoHalvingMNRewardBlock, num)
}
func (c *ChainConfig) IsTIPXDCX(num *big.Int) bool {
- return isForked(common.TIPXDCX, num)
+ return isForked(c.TIPXDCXBlock, num)
}
func (c *ChainConfig) IsTIPXDCXMiner(num *big.Int) bool {
- return isForked(common.TIPXDCX, num) && !isForked(common.TIPXDCXMinerDisable, num)
+ return isForked(c.TIPXDCXBlock, num) && !isForked(c.TIPXDCXMinerDisableBlock, num)
}
func (c *ChainConfig) IsTIPXDCXReceiver(num *big.Int) bool {
- return isForked(common.TIPXDCX, num) && !isForked(common.TIPXDCXReceiverDisable, num)
+ return isForked(c.TIPXDCXBlock, num) && !isForked(c.TIPXDCXReceiverDisableBlock, num)
}
func (c *ChainConfig) IsXDCxDisable(num *big.Int) bool {
- return isForked(common.TIPXDCXMinerDisable, num)
+ return isForked(c.TIPXDCXMinerDisableBlock, num)
}
func (c *ChainConfig) IsTIPXDCXLending(num *big.Int) bool {
- return isForked(common.TIPXDCXLending, num)
+ return isForked(c.TIPXDCXLendingBlock, num)
}
func (c *ChainConfig) IsTIPXDCXCancellationFee(num *big.Int) bool {
- return isForked(common.TIPXDCXCancellationFee, num)
+ return isForked(c.TIPXDCXCancellationFeeBlock, num)
}
func (c *ChainConfig) IsTIPUpgradeReward(num *big.Int) bool {
- return isForked(common.TIPUpgradeReward, num)
+ return isForked(c.TIPUpgradeRewardBlock, num)
}
func (c *ChainConfig) IsTIPUpgradePenalty(num *big.Int) bool {
- return isForked(common.TipUpgradePenalty, num)
+ return isForked(c.TIPUpgradePenaltyBlock, num)
}
func (c *ChainConfig) IsTIPEpochHalving(num *big.Int) bool {
- return isForked(common.TIPEpochHalving, num)
+ return isForked(c.TIPEpochHalvingBlock, num)
+}
+
+// IsXDPoSV2 returns whether num is either equal to the XDPoS V2 switch block or greater.
+func (c *ChainConfig) IsXDPoSV2(num *big.Int) bool {
+ return c.XDPoS != nil && c.XDPoS.V2 != nil && isForked(c.XDPoS.V2.SwitchBlock, num)
}
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
@@ -1195,6 +1984,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) {
return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock)
}
+ if isForkIncompatible(c.TIP2019Block, newcfg.TIP2019Block, head) {
+ return newCompatError("TIP2019 fork block", c.TIP2019Block, newcfg.TIP2019Block)
+ }
if isForkIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) {
return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock)
}
@@ -1229,15 +2021,54 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
if isForkIncompatible(c.IstanbulBlock, newcfg.IstanbulBlock, head) {
return newCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock)
}
+ if isForkIncompatible(c.TIPSigningBlock, newcfg.TIPSigningBlock, head) {
+ return newCompatError("TIPSigning fork block", c.TIPSigningBlock, newcfg.TIPSigningBlock)
+ }
+ if isForkIncompatible(c.TIPRandomizeBlock, newcfg.TIPRandomizeBlock, head) {
+ return newCompatError("TIPRandomize fork block", c.TIPRandomizeBlock, newcfg.TIPRandomizeBlock)
+ }
+ if isForkIncompatible(c.TIPIncreaseMasternodesBlock, newcfg.TIPIncreaseMasternodesBlock, head) {
+ return newCompatError("TIPIncreaseMasternodes fork block", c.TIPIncreaseMasternodesBlock, newcfg.TIPIncreaseMasternodesBlock)
+ }
+ if isForkIncompatible(c.DenylistBlock, newcfg.DenylistBlock, head) {
+ return newCompatError("Denylist fork block", c.DenylistBlock, newcfg.DenylistBlock)
+ }
+ if isForkIncompatible(c.TIPNoHalvingMNRewardBlock, newcfg.TIPNoHalvingMNRewardBlock, head) {
+ return newCompatError("TIPNoHalvingMNReward fork block", c.TIPNoHalvingMNRewardBlock, newcfg.TIPNoHalvingMNRewardBlock)
+ }
+ if isForkIncompatible(c.TIPXDCXBlock, newcfg.TIPXDCXBlock, head) {
+ return newCompatError("TIPXDCX fork block", c.TIPXDCXBlock, newcfg.TIPXDCXBlock)
+ }
+ if isForkIncompatible(c.TIPXDCXLendingBlock, newcfg.TIPXDCXLendingBlock, head) {
+ return newCompatError("TIPXDCXLending fork block", c.TIPXDCXLendingBlock, newcfg.TIPXDCXLendingBlock)
+ }
+ if isForkIncompatible(c.TIPXDCXCancellationFeeBlock, newcfg.TIPXDCXCancellationFeeBlock, head) {
+ return newCompatError("TIPXDCXCancellationFee fork block", c.TIPXDCXCancellationFeeBlock, newcfg.TIPXDCXCancellationFeeBlock)
+ }
+ if isForkIncompatible(c.TIPTRC21FeeBlock, newcfg.TIPTRC21FeeBlock, head) {
+ return newCompatError("TIPTRC21Fee fork block", c.TIPTRC21FeeBlock, newcfg.TIPTRC21FeeBlock)
+ }
if isForkIncompatible(c.BerlinBlock, newcfg.BerlinBlock, head) {
return newCompatError("Berlin fork block", c.BerlinBlock, newcfg.BerlinBlock)
}
if isForkIncompatible(c.LondonBlock, newcfg.LondonBlock, head) {
return newCompatError("London fork block", c.LondonBlock, newcfg.LondonBlock)
}
+ if isForkIncompatible(c.MergeBlock, newcfg.MergeBlock, head) {
+ return newCompatError("Merge fork block", c.MergeBlock, newcfg.MergeBlock)
+ }
if isForkIncompatible(c.ShanghaiBlock, newcfg.ShanghaiBlock, head) {
return newCompatError("Shanghai fork block", c.ShanghaiBlock, newcfg.ShanghaiBlock)
}
+ if isForkIncompatible(c.Gas50xBlock, newcfg.Gas50xBlock, head) {
+ return newCompatError("Gas50x fork block", c.Gas50xBlock, newcfg.Gas50xBlock)
+ }
+ if isForkIncompatible(c.TIPXDCXMinerDisableBlock, newcfg.TIPXDCXMinerDisableBlock, head) {
+ return newCompatError("TIPXDCXMinerDisable fork block", c.TIPXDCXMinerDisableBlock, newcfg.TIPXDCXMinerDisableBlock)
+ }
+ if isForkIncompatible(c.TIPXDCXReceiverDisableBlock, newcfg.TIPXDCXReceiverDisableBlock, head) {
+ return newCompatError("TIPXDCXReceiverDisable fork block", c.TIPXDCXReceiverDisableBlock, newcfg.TIPXDCXReceiverDisableBlock)
+ }
if isForkIncompatible(c.Eip1559Block, newcfg.Eip1559Block, head) {
return newCompatError("Eip1559 fork block", c.Eip1559Block, newcfg.Eip1559Block)
}
@@ -1250,6 +2081,18 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
if isForkIncompatible(c.OsakaBlock, newcfg.OsakaBlock, head) {
return newCompatError("Osaka fork block", c.OsakaBlock, newcfg.OsakaBlock)
}
+ if isForkIncompatible(c.DynamicGasLimitBlock, newcfg.DynamicGasLimitBlock, head) {
+ return newCompatError("DynamicGasLimit fork block", c.DynamicGasLimitBlock, newcfg.DynamicGasLimitBlock)
+ }
+ if isForkIncompatible(c.TIPUpgradeRewardBlock, newcfg.TIPUpgradeRewardBlock, head) {
+ return newCompatError("TIPUpgradeReward fork block", c.TIPUpgradeRewardBlock, newcfg.TIPUpgradeRewardBlock)
+ }
+ if isForkIncompatible(c.TIPUpgradePenaltyBlock, newcfg.TIPUpgradePenaltyBlock, head) {
+ return newCompatError("TIPUpgradePenalty fork block", c.TIPUpgradePenaltyBlock, newcfg.TIPUpgradePenaltyBlock)
+ }
+ if isForkIncompatible(c.TIPEpochHalvingBlock, newcfg.TIPEpochHalvingBlock, head) {
+ return newCompatError("TIPEpochHalving fork block", c.TIPEpochHalvingBlock, newcfg.TIPEpochHalvingBlock)
+ }
if !XDPoSConfigEqual(c.XDPoS, newcfg.XDPoS) {
storedblock := big.NewInt(1)
if c.XDPoS != nil && c.XDPoS.V2 != nil && c.XDPoS.V2.SwitchBlock != nil {
@@ -1371,3 +2214,106 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
IsOsaka: c.IsOsaka(num),
}
}
+
+// GatherForks gathers all the known forks and creates a sorted list of
+// block number based forks.
+func (c *ChainConfig) GatherForks() []uint64 {
+ // Gather all the fork block numbers via reflection
+ kind := reflect.TypeFor[ChainConfig]()
+ conf := reflect.ValueOf(c).Elem()
+ var (
+ forksByBlock []uint64
+ )
+ for i := 0; i < kind.NumField(); i++ {
+ // Fetch the next field and skip non-fork rules
+ field := kind.Field(i)
+ if !strings.HasSuffix(field.Name, "Block") {
+ continue
+ }
+
+ // Extract the fork rule block number and aggregate it
+ if field.Type == reflect.TypeFor[*big.Int]() {
+ if rule := conf.Field(i).Interface().(*big.Int); rule != nil {
+ forksByBlock = append(forksByBlock, rule.Uint64())
+ }
+ }
+ }
+ if c.XDPoS != nil && c.XDPoS.V2 != nil && c.XDPoS.V2.SwitchBlock != nil {
+ forksByBlock = append(forksByBlock, c.XDPoS.V2.SwitchBlock.Uint64())
+ }
+ slices.Sort(forksByBlock)
+
+ // Deduplicate fork identifiers applying multiple forks
+ for i := 1; i < len(forksByBlock); i++ {
+ if forksByBlock[i] == forksByBlock[i-1] {
+ forksByBlock = append(forksByBlock[:i], forksByBlock[i+1:]...)
+ i--
+ }
+ }
+ // Skip any forks in block 0, that's the genesis ruleset
+ if len(forksByBlock) > 0 && forksByBlock[0] == 0 {
+ forksByBlock = forksByBlock[1:]
+ }
+ return forksByBlock
+}
+
+// ActiveForks returns the list of active forks at the given block height.
+// The returned list is sorted in alphabetical order.
+func (c *ChainConfig) ActiveForks(block *big.Int) []string {
+ var features = map[forks.Fork]bool{
+ forks.Homestead: c.IsHomestead(block),
+ forks.DAO: c.IsDAOFork(block),
+ forks.TIP2019: c.IsTIP2019(block),
+ forks.TangerineWhistle: c.IsEIP150(block),
+ forks.SpuriousDragon: c.IsEIP155(block),
+ forks.EIP158: c.IsEIP158(block),
+ forks.Byzantium: c.IsByzantium(block),
+ forks.Constantinople: c.IsConstantinople(block),
+ forks.Petersburg: c.IsPetersburg(block),
+ forks.Istanbul: c.IsIstanbul(block),
+ forks.TIPSigning: c.IsTIPSigning(block),
+ forks.TIPRandomize: c.IsTIPRandomize(block),
+ forks.TIPIncreaseMasternodes: c.IsTIPIncreaseMasternodes(block),
+ forks.Denylist: c.IsDenylist(block),
+ forks.TIPNoHalvingMNReward: c.IsTIPNoHalvingMNReward(block),
+ forks.TIPXDCX: c.IsTIPXDCX(block),
+ forks.TIPXDCXLending: c.IsTIPXDCXLending(block),
+ forks.TIPXDCXCancellationFee: c.IsTIPXDCXCancellationFee(block),
+ forks.TIPTRC21Fee: c.IsTIPTRC21Fee(block),
+ forks.Berlin: c.IsBerlin(block),
+ forks.London: c.IsLondon(block),
+ forks.Merge: c.IsMerge(block),
+ forks.Shanghai: c.IsShanghai(block),
+ forks.Gas50x: c.IsGas50x(block),
+ forks.XDPoSV2: c.IsXDPoSV2(block),
+ forks.TIPXDCXMiner: c.IsTIPXDCXMiner(block),
+ forks.TIPXDCXReceiver: c.IsTIPXDCXReceiver(block),
+ forks.XDCxDisable: c.IsXDCxDisable(block),
+ forks.EIP1559: c.IsEIP1559(block),
+ forks.Cancun: c.IsCancun(block),
+ forks.DynamicGasLimit: c.IsDynamicGasLimit(block),
+ forks.TIPUpgradeReward: c.IsTIPUpgradeReward(block),
+ forks.TIPUpgradePenalty: c.IsTIPUpgradePenalty(block),
+ forks.TIPEpochHalving: c.IsTIPEpochHalving(block),
+ forks.Prague: c.IsPrague(block),
+ forks.Osaka: c.IsOsaka(block),
+ }
+ var activeForks []string
+ for fork, active := range features {
+ if active {
+ activeForks = append(activeForks, fork.String())
+ }
+ }
+ slices.Sort(activeForks)
+ return activeForks
+}
+
+// ActiveSystemContracts returns the currently active system contracts at the
+// given block height.
+func (c *ChainConfig) ActiveSystemContracts(block uint64) map[string]common.Address {
+ active := make(map[string]common.Address)
+ if c.IsPrague(new(big.Int).SetUint64(block)) {
+ active["HISTORY_STORAGE_ADDRESS"] = HistoryStorageAddress
+ }
+ return active
+}
diff --git a/params/config_test.go b/params/config_test.go
index 99a653d30710..22f13edd3850 100644
--- a/params/config_test.go
+++ b/params/config_test.go
@@ -18,8 +18,11 @@ package params
import (
"encoding/json"
+ "errors"
+ "math"
"math/big"
"reflect"
+ "strings"
"testing"
"github.com/XinFinOrg/XDPoSChain/common"
@@ -33,8 +36,18 @@ func TestCheckCompatible(t *testing.T) {
wantErr *ConfigCompatError
}
tests := []test{
- {stored: AllEthashProtocolChanges, new: AllEthashProtocolChanges, head: 0, wantErr: nil},
- {stored: AllEthashProtocolChanges, new: AllEthashProtocolChanges, head: 100, wantErr: nil},
+ {
+ stored: AllEthashProtocolChanges,
+ new: AllEthashProtocolChanges,
+ head: 0,
+ wantErr: nil,
+ },
+ {
+ stored: AllEthashProtocolChanges,
+ new: AllEthashProtocolChanges,
+ head: 100,
+ wantErr: nil,
+ },
{
stored: &ChainConfig{EIP150Block: big.NewInt(10)},
new: &ChainConfig{EIP150Block: big.NewInt(20)},
@@ -63,6 +76,17 @@ func TestCheckCompatible(t *testing.T) {
RewindTo: 0,
},
},
+ {
+ stored: &ChainConfig{TIP2019Block: big.NewInt(10)},
+ new: &ChainConfig{TIP2019Block: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIP2019 fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
{
stored: &ChainConfig{HomesteadBlock: big.NewInt(30), EIP150Block: big.NewInt(10)},
new: &ChainConfig{HomesteadBlock: big.NewInt(25), EIP150Block: big.NewInt(20)},
@@ -74,6 +98,248 @@ func TestCheckCompatible(t *testing.T) {
RewindTo: 9,
},
},
+ {
+ stored: &ChainConfig{TIPSigningBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPSigningBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPSigning fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPRandomizeBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPRandomizeBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPRandomize fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{DenylistBlock: big.NewInt(10)},
+ new: &ChainConfig{DenylistBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Denylist fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPNoHalvingMNRewardBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPNoHalvingMNRewardBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPNoHalvingMNReward fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPXDCXBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPXDCXBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPXDCX fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPXDCXLendingBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPXDCXLendingBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPXDCXLending fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPXDCXCancellationFeeBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPXDCXCancellationFeeBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPXDCXCancellationFee fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPTRC21FeeBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPTRC21FeeBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPTRC21Fee fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{BerlinBlock: big.NewInt(10)},
+ new: &ChainConfig{BerlinBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Berlin fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{LondonBlock: big.NewInt(10)},
+ new: &ChainConfig{LondonBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "London fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{MergeBlock: big.NewInt(10)},
+ new: &ChainConfig{MergeBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Merge fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{ShanghaiBlock: big.NewInt(10)},
+ new: &ChainConfig{ShanghaiBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Shanghai fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPXDCXMinerDisableBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPXDCXMinerDisableBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPXDCXMinerDisable fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPXDCXReceiverDisableBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPXDCXReceiverDisableBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPXDCXReceiverDisable fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{Eip1559Block: big.NewInt(10)},
+ new: &ChainConfig{Eip1559Block: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Eip1559 fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{CancunBlock: big.NewInt(10)},
+ new: &ChainConfig{CancunBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Cancun fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{PragueBlock: big.NewInt(10)},
+ new: &ChainConfig{PragueBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Prague fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{OsakaBlock: big.NewInt(10)},
+ new: &ChainConfig{OsakaBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "Osaka fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{DynamicGasLimitBlock: big.NewInt(10)},
+ new: &ChainConfig{DynamicGasLimitBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "DynamicGasLimit fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPUpgradeRewardBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPUpgradeRewardBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPUpgradeReward fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPUpgradePenaltyBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPUpgradePenaltyBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPUpgradePenalty fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
+ {
+ stored: &ChainConfig{TIPEpochHalvingBlock: big.NewInt(10)},
+ new: &ChainConfig{TIPEpochHalvingBlock: big.NewInt(20)},
+ head: 15,
+ wantErr: &ConfigCompatError{
+ What: "TIPEpochHalving fork block",
+ StoredConfig: big.NewInt(10),
+ NewConfig: big.NewInt(20),
+ RewindTo: 9,
+ },
+ },
}
for _, test := range tests {
@@ -84,6 +350,60 @@ func TestCheckCompatible(t *testing.T) {
}
}
+func TestChainConfigValidateForStartup(t *testing.T) {
+ t.Run("missing field", func(t *testing.T) {
+ cfg := &ChainConfig{}
+ err := cfg.CheckConfigForkOrder()
+ if !errors.Is(err, ErrMissingForkSwitch) {
+ t.Fatalf("unexpected error: have %v want %v", err, ErrMissingForkSwitch)
+ }
+ if err == nil || err.Error() != "invalid chain config: missing fork switch ChainID" {
+ t.Fatalf("unexpected error string: %v", err)
+ }
+ })
+
+ t.Run("valid config", func(t *testing.T) {
+ cfg := &ChainConfig{
+ ChainID: big.NewInt(1),
+ TIPTRC21FeeBlock: big.NewInt(0),
+ }
+ if err := cfg.CheckConfigForkOrder(); err != nil {
+ t.Fatalf("ValidateForStartup failed: %v", err)
+ }
+ })
+}
+
+func TestXDPoSMockChainConfigDeclaresModernForks(t *testing.T) {
+ config := TestXDPoSMockChainConfig
+ if !assert.NotNil(t, config) {
+ return
+ }
+ assertBlock := func(name string, got *big.Int) {
+ t.Helper()
+ if assert.NotNil(t, got, "%s must be explicitly declared on TestXDPoSMockChainConfig", name) {
+ assert.Zero(t, got.Cmp(common.Big0), "%s must be active from genesis on TestXDPoSMockChainConfig", name)
+ }
+ }
+
+ assertBlock("TIP2019Block", config.TIP2019Block)
+ assertBlock("TIPSigningBlock", config.TIPSigningBlock)
+ assertBlock("TIPRandomizeBlock", config.TIPRandomizeBlock)
+ assertBlock("TIPIncreaseMasternodesBlock", config.TIPIncreaseMasternodesBlock)
+ assertBlock("TIPNoHalvingMNRewardBlock", config.TIPNoHalvingMNRewardBlock)
+ assertBlock("TIPXDCXBlock", config.TIPXDCXBlock)
+ assertBlock("TIPXDCXLendingBlock", config.TIPXDCXLendingBlock)
+ assertBlock("TIPXDCXCancellationFeeBlock", config.TIPXDCXCancellationFeeBlock)
+ assertBlock("TIPTRC21Fee", config.TIPTRC21FeeBlock)
+ assertBlock("BerlinBlock", config.BerlinBlock)
+ assertBlock("LondonBlock", config.LondonBlock)
+ assertBlock("MergeBlock", config.MergeBlock)
+ assertBlock("ShanghaiBlock", config.ShanghaiBlock)
+ assertBlock("Eip1559Block", config.Eip1559Block)
+ assertBlock("CancunBlock", config.CancunBlock)
+ assertBlock("PragueBlock", config.PragueBlock)
+ assertBlock("OsakaBlock", config.OsakaBlock)
+}
+
func TestUpdateV2Config(t *testing.T) {
TestXDPoSMockChainConfig.XDPoS.V2.BuildConfigIndex()
c := TestXDPoSMockChainConfig.XDPoS.V2.CurrentConfig
@@ -134,6 +454,95 @@ func TestBuildConfigIndexDescendingOrder(t *testing.T) {
assert.Equal(t, []uint64{15, 10, 5, 2, 0}, v2.ConfigIndex())
}
+func TestV2ConfigIndexReturnsCopy(t *testing.T) {
+ v2 := &V2{
+ configIndex: []uint64{3, 2, 1},
+ }
+
+ index := v2.ConfigIndex()
+ index[0] = 99
+
+ assert.Equal(t, []uint64{3, 2, 1}, v2.ConfigIndex())
+}
+
+func TestChainConfigCloneDeepCopiesNestedConfig(t *testing.T) {
+ original := &ChainConfig{
+ ChainID: big.NewInt(50),
+ TIP2019Block: big.NewInt(10),
+ Gas50xBlock: big.NewInt(15),
+ TIPXDCXMinerDisableBlock: big.NewInt(20),
+ TIPXDCXReceiverDisableBlock: big.NewInt(25),
+ OsakaBlock: big.NewInt(30),
+ Ethash: new(EthashConfig),
+ XDPoS: &XDPoSConfig{
+ V2: &V2{
+ SwitchEpoch: 12,
+ SwitchBlock: big.NewInt(99),
+ CurrentConfig: &V2Config{
+ SwitchRound: 1,
+ },
+ AllConfigs: map[uint64]*V2Config{
+ 1: {SwitchRound: 1},
+ },
+ },
+ },
+ }
+ original.XDPoS.V2.BuildConfigIndex()
+
+ clone := original.Clone()
+ if assert.NotNil(t, clone) {
+ assert.NotSame(t, original, clone)
+ assert.NotSame(t, original.ChainID, clone.ChainID)
+ assert.NotSame(t, original.TIP2019Block, clone.TIP2019Block)
+ assert.NotSame(t, original.Gas50xBlock, clone.Gas50xBlock)
+ assert.NotSame(t, original.TIPXDCXMinerDisableBlock, clone.TIPXDCXMinerDisableBlock)
+ assert.NotSame(t, original.TIPXDCXReceiverDisableBlock, clone.TIPXDCXReceiverDisableBlock)
+ assert.NotSame(t, original.OsakaBlock, clone.OsakaBlock)
+ assert.NotSame(t, original.XDPoS, clone.XDPoS)
+ assert.NotSame(t, original.XDPoS.V2, clone.XDPoS.V2)
+ assert.NotSame(t, original.XDPoS.V2.SwitchBlock, clone.XDPoS.V2.SwitchBlock)
+ assert.NotSame(t, original.XDPoS.V2.CurrentConfig, clone.XDPoS.V2.CurrentConfig)
+ assert.NotSame(t, original.XDPoS.V2.AllConfigs[1], clone.XDPoS.V2.AllConfigs[1])
+
+ clone.ChainID.SetInt64(999)
+ clone.Gas50xBlock.SetInt64(1)
+ clone.XDPoS.V2.SwitchBlock.SetInt64(123)
+ clone.XDPoS.V2.CurrentConfig.SwitchRound = 7
+ cloneIndex := clone.XDPoS.V2.ConfigIndex()
+ cloneIndex[0] = 77
+
+ assert.Equal(t, int64(50), original.ChainID.Int64())
+ assert.Equal(t, int64(15), original.Gas50xBlock.Int64())
+ assert.Equal(t, int64(99), original.XDPoS.V2.SwitchBlock.Int64())
+ assert.Equal(t, uint64(1), original.XDPoS.V2.CurrentConfig.SwitchRound)
+ assert.Equal(t, []uint64{1}, original.XDPoS.V2.ConfigIndex())
+ }
+}
+
+func TestChainConfigGas50xBlockDefaults(t *testing.T) {
+ tests := []struct {
+ name string
+ cfg *ChainConfig
+ want int64
+ }{
+ {name: "mainnet", cfg: XDCMainnetChainConfig, want: 80370000},
+ {name: "testnet", cfg: TestnetChainConfig, want: 56828700},
+ {name: "devnet", cfg: DevnetChainConfig, want: 0},
+ {name: "localnet", cfg: LocalnetChainConfig, want: 0},
+ {name: "custom default", cfg: &ChainConfig{}, want: 0},
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ got := tc.cfg.Gas50xBlock
+ if got == nil {
+ got = big.NewInt(0)
+ }
+ assert.Equal(t, tc.want, got.Int64())
+ })
+ }
+}
+
// Test switch epoch is switchblock divide into epoch per block
func TestSwitchEpoch(t *testing.T) {
config := XDCMainnetChainConfig.XDPoS
@@ -153,6 +562,401 @@ func TestSwitchEpoch(t *testing.T) {
assert.Equal(t, config.V2.SwitchEpoch, config.V2.SwitchBlock.Uint64()/epoch)
}
+func TestBuiltInV2SwitchBlockConstants(t *testing.T) {
+ assert.Equal(t, MainnetV2SwitchBlock, XDCMainnetChainConfig.XDPoS.V2.SwitchBlock.Uint64())
+ assert.Equal(t, XDCMainnetChainConfig.XDPoS.V2.SwitchBlock.Uint64()/XDCMainnetChainConfig.XDPoS.Epoch, XDCMainnetChainConfig.XDPoS.V2.SwitchEpoch)
+
+ assert.Equal(t, TestnetV2SwitchBlock, TestnetChainConfig.XDPoS.V2.SwitchBlock.Uint64())
+ assert.Equal(t, TestnetChainConfig.XDPoS.V2.SwitchBlock.Uint64()/TestnetChainConfig.XDPoS.Epoch, TestnetChainConfig.XDPoS.V2.SwitchEpoch)
+
+ assert.Equal(t, DevnetV2SwitchBlock, DevnetChainConfig.XDPoS.V2.SwitchBlock.Uint64())
+ assert.Equal(t, DevnetChainConfig.XDPoS.V2.SwitchBlock.Uint64()/DevnetChainConfig.XDPoS.Epoch, DevnetChainConfig.XDPoS.V2.SwitchEpoch)
+}
+
+func TestXDCChainConfigsDeclareForkBlocks(t *testing.T) {
+ tests := []struct {
+ name string
+ config *ChainConfig
+ tip2019Block *big.Int
+ tipSigningBlock *big.Int
+ tipRandomizeBlock *big.Int
+ tipIncreaseMasternodesBlock *big.Int
+ denylistBlock *big.Int
+ tipNoHalvingMNRewardBlock *big.Int
+ tipXDCXBlock *big.Int
+ tipXDCXLendingBlock *big.Int
+ tipXDCXCancellationFeeBlock *big.Int
+ tipTRC21Fee *big.Int
+ berlinBlock *big.Int
+ londonBlock *big.Int
+ mergeBlock *big.Int
+ shanghaiBlock *big.Int
+ tipXDCXMinerDisable *big.Int
+ tipXDCXReceiverDisable *big.Int
+ eip1559Block *big.Int
+ cancunBlock *big.Int
+ pragueBlock *big.Int
+ osakaBlock *big.Int
+ dynamicGasLimitBlock *big.Int
+ tipUpgradeRewardBlock *big.Int
+ tipUpgradePenaltyBlock *big.Int
+ tipEpochHalvingBlock *big.Int
+ }{
+ {
+ name: "mainnet",
+ config: XDCMainnetChainConfig,
+ tip2019Block: big.NewInt(1),
+ tipSigningBlock: big.NewInt(3000000),
+ tipRandomizeBlock: big.NewInt(3464000),
+ tipIncreaseMasternodesBlock: big.NewInt(5000000),
+ denylistBlock: big.NewInt(38383838),
+ tipNoHalvingMNRewardBlock: big.NewInt(38383838),
+ tipXDCXBlock: big.NewInt(38383838),
+ tipXDCXLendingBlock: big.NewInt(38383838),
+ tipXDCXCancellationFeeBlock: big.NewInt(38383838),
+ tipTRC21Fee: big.NewInt(38383838),
+ berlinBlock: big.NewInt(76321000),
+ londonBlock: big.NewInt(76321000),
+ mergeBlock: big.NewInt(76321000),
+ shanghaiBlock: big.NewInt(76321000),
+ tipXDCXMinerDisable: big.NewInt(80370000),
+ tipXDCXReceiverDisable: big.NewInt(80370900),
+ eip1559Block: big.NewInt(98800200),
+ cancunBlock: big.NewInt(98802000),
+ pragueBlock: nil,
+ osakaBlock: nil,
+ dynamicGasLimitBlock: nil,
+ tipUpgradeRewardBlock: nil,
+ tipUpgradePenaltyBlock: nil,
+ tipEpochHalvingBlock: nil,
+ },
+ {
+ name: "testnet",
+ config: TestnetChainConfig,
+ tip2019Block: big.NewInt(1),
+ tipSigningBlock: big.NewInt(3000000),
+ tipRandomizeBlock: big.NewInt(3464000),
+ tipIncreaseMasternodesBlock: big.NewInt(5000000),
+ denylistBlock: big.NewInt(23779191),
+ tipNoHalvingMNRewardBlock: big.NewInt(23779191),
+ tipXDCXBlock: big.NewInt(23779191),
+ tipXDCXLendingBlock: big.NewInt(23779191),
+ tipXDCXCancellationFeeBlock: big.NewInt(23779191),
+ tipTRC21Fee: big.NewInt(23779191),
+ berlinBlock: big.NewInt(61290000),
+ londonBlock: big.NewInt(61290000),
+ mergeBlock: big.NewInt(61290000),
+ shanghaiBlock: big.NewInt(61290000),
+ tipXDCXMinerDisable: big.NewInt(61290000),
+ tipXDCXReceiverDisable: big.NewInt(66825000),
+ eip1559Block: big.NewInt(71550000),
+ cancunBlock: big.NewInt(71551800),
+ pragueBlock: nil,
+ osakaBlock: nil,
+ dynamicGasLimitBlock: nil,
+ tipUpgradeRewardBlock: nil,
+ tipUpgradePenaltyBlock: nil,
+ tipEpochHalvingBlock: nil,
+ },
+ {
+ name: "devnet",
+ config: DevnetChainConfig,
+ tip2019Block: big.NewInt(0),
+ tipSigningBlock: big.NewInt(0),
+ tipRandomizeBlock: big.NewInt(0),
+ tipIncreaseMasternodesBlock: big.NewInt(0),
+ denylistBlock: big.NewInt(0),
+ tipNoHalvingMNRewardBlock: big.NewInt(0),
+ tipXDCXBlock: big.NewInt(0),
+ tipXDCXLendingBlock: big.NewInt(0),
+ tipXDCXCancellationFeeBlock: big.NewInt(0),
+ tipTRC21Fee: big.NewInt(0),
+ berlinBlock: big.NewInt(0),
+ londonBlock: big.NewInt(0),
+ mergeBlock: big.NewInt(0),
+ shanghaiBlock: big.NewInt(0),
+ tipXDCXMinerDisable: big.NewInt(0),
+ tipXDCXReceiverDisable: big.NewInt(0),
+ eip1559Block: big.NewInt(250000),
+ cancunBlock: big.NewInt(250000),
+ pragueBlock: big.NewInt(5000000),
+ osakaBlock: nil,
+ dynamicGasLimitBlock: big.NewInt(5000000),
+ tipUpgradeRewardBlock: big.NewInt(5000000),
+ tipUpgradePenaltyBlock: big.NewInt(5000000),
+ tipEpochHalvingBlock: nil,
+ },
+ {
+ name: "localnet",
+ config: LocalnetChainConfig,
+ tip2019Block: big.NewInt(0),
+ tipSigningBlock: big.NewInt(0),
+ tipRandomizeBlock: big.NewInt(0),
+ tipIncreaseMasternodesBlock: big.NewInt(0),
+ denylistBlock: big.NewInt(0),
+ tipNoHalvingMNRewardBlock: big.NewInt(0),
+ tipXDCXBlock: big.NewInt(0),
+ tipXDCXLendingBlock: big.NewInt(0),
+ tipXDCXCancellationFeeBlock: big.NewInt(0),
+ tipTRC21Fee: big.NewInt(0),
+ berlinBlock: big.NewInt(0),
+ londonBlock: big.NewInt(0),
+ mergeBlock: big.NewInt(0),
+ shanghaiBlock: big.NewInt(0),
+ tipXDCXMinerDisable: big.NewInt(0),
+ tipXDCXReceiverDisable: big.NewInt(0),
+ eip1559Block: big.NewInt(0),
+ cancunBlock: big.NewInt(0),
+ pragueBlock: nil,
+ osakaBlock: nil,
+ dynamicGasLimitBlock: nil,
+ tipUpgradeRewardBlock: nil,
+ tipUpgradePenaltyBlock: nil,
+ tipEpochHalvingBlock: nil,
+ },
+ }
+
+ assertBlock := func(t *testing.T, fork string, got, want *big.Int) {
+ t.Helper()
+ if want == nil {
+ assert.Nil(t, got, "%s block must be nil when unscheduled", fork)
+ return
+ }
+ if assert.NotNil(t, got, "%s block must be declared", fork) {
+ assert.Equal(t, 0, got.Cmp(want), "%s block mismatch", fork)
+ }
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ if !assert.NotNil(t, test.config, "chain config must not be nil") {
+ return
+ }
+ assertBlock(t, "TIP2019", test.config.TIP2019Block, test.tip2019Block)
+ assertBlock(t, "TIPSigning", test.config.TIPSigningBlock, test.tipSigningBlock)
+ assertBlock(t, "TIPRandomize", test.config.TIPRandomizeBlock, test.tipRandomizeBlock)
+ assertBlock(t, "TIPIncreaseMasternodes", test.config.TIPIncreaseMasternodesBlock, test.tipIncreaseMasternodesBlock)
+ assertBlock(t, "DenylistHardFork", test.config.DenylistBlock, test.denylistBlock)
+ assertBlock(t, "TIPNoHalvingMNReward", test.config.TIPNoHalvingMNRewardBlock, test.tipNoHalvingMNRewardBlock)
+ assertBlock(t, "TIPXDCX", test.config.TIPXDCXBlock, test.tipXDCXBlock)
+ assertBlock(t, "TIPXDCXLending", test.config.TIPXDCXLendingBlock, test.tipXDCXLendingBlock)
+ assertBlock(t, "TIPXDCXCancellationFee", test.config.TIPXDCXCancellationFeeBlock, test.tipXDCXCancellationFeeBlock)
+ assertBlock(t, "TIPTRC21Fee", test.config.TIPTRC21FeeBlock, test.tipTRC21Fee)
+ assertBlock(t, "Berlin", test.config.BerlinBlock, test.berlinBlock)
+ assertBlock(t, "London", test.config.LondonBlock, test.londonBlock)
+ assertBlock(t, "Merge", test.config.MergeBlock, test.mergeBlock)
+ assertBlock(t, "Shanghai", test.config.ShanghaiBlock, test.shanghaiBlock)
+ assertBlock(t, "TIPXDCXMinerDisable", test.config.TIPXDCXMinerDisableBlock, test.tipXDCXMinerDisable)
+ assertBlock(t, "TIPXDCXReceiverDisable", test.config.TIPXDCXReceiverDisableBlock, test.tipXDCXReceiverDisable)
+ assertBlock(t, "Eip1559", test.config.Eip1559Block, test.eip1559Block)
+ assertBlock(t, "Cancun", test.config.CancunBlock, test.cancunBlock)
+ assertBlock(t, "Prague", test.config.PragueBlock, test.pragueBlock)
+ assertBlock(t, "Osaka", test.config.OsakaBlock, test.osakaBlock)
+ assertBlock(t, "DynamicGasLimit", test.config.DynamicGasLimitBlock, test.dynamicGasLimitBlock)
+ assertBlock(t, "TIPUpgradeReward", test.config.TIPUpgradeRewardBlock, test.tipUpgradeRewardBlock)
+ assertBlock(t, "TIPUpgradePenalty", test.config.TIPUpgradePenaltyBlock, test.tipUpgradePenaltyBlock)
+ assertBlock(t, "TIPEpochHalving", test.config.TIPEpochHalvingBlock, test.tipEpochHalvingBlock)
+ })
+ }
+}
+
+func TestForkActivationIgnoresCommonFallbacks(t *testing.T) {
+ const zeroAddress0x = "0x0000000000000000000000000000000000000000"
+ config := &ChainConfig{}
+ block := big.NewInt(1)
+
+ assert.False(t, config.IsTIP2019(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPSigning(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPRandomize(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPIncreaseMasternodes(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsDenylist(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPNoHalvingMNReward(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPXDCX(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPXDCXLending(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPXDCXCancellationFee(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsBerlin(block))
+ assert.False(t, config.IsLondon(block))
+ assert.False(t, config.IsMerge(block))
+ assert.False(t, config.IsShanghai(block))
+ assert.False(t, config.IsTIPXDCXMiner(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPXDCXReceiver(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsXDCxDisable(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsCancun(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsPrague(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsOsaka(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsDynamicGasLimit(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPUpgradeReward(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPUpgradePenalty(big.NewInt(math.MaxInt64)))
+ assert.False(t, config.IsTIPEpochHalving(big.NewInt(math.MaxInt64)))
+
+ description := config.Description()
+ assertDescriptionLineValue := func(t *testing.T, label, value string) {
+ t.Helper()
+ for _, line := range strings.Split(description, "\n") {
+ if strings.Contains(line, label) {
+ assert.Contains(t, line, value, "description line for %s should contain %s", label, value)
+ return
+ }
+ }
+ assert.Failf(t, "missing description line", "description must contain a line for %s", label)
+ }
+
+ assertDescriptionLineValue(t, "TIP2019:", "")
+ assertDescriptionLineValue(t, "TIPSigning:", "")
+ assertDescriptionLineValue(t, "TIPRandomize:", "")
+ assertDescriptionLineValue(t, "TIPIncreaseMasternodes:", "")
+ assertDescriptionLineValue(t, "Denylist:", "")
+ assertDescriptionLineValue(t, "TIPNoHalvingMNReward:", "")
+ assertDescriptionLineValue(t, "TIPXDCX:", "")
+ assertDescriptionLineValue(t, "TIPXDCXLending:", "")
+ assertDescriptionLineValue(t, "TIPXDCXCancellationFee:", "")
+ assertDescriptionLineValue(t, "TIPTRC21Fee:", "")
+ assertDescriptionLineValue(t, "Berlin:", "")
+ assertDescriptionLineValue(t, "London:", "")
+ assertDescriptionLineValue(t, "Merge:", "")
+ assertDescriptionLineValue(t, "Shanghai:", "")
+ assertDescriptionLineValue(t, "TIPXDCXMinerDisable:", "")
+ assertDescriptionLineValue(t, "TIPXDCXReceiverDisable:", "")
+ assertDescriptionLineValue(t, "Cancun:", "")
+ assertDescriptionLineValue(t, "Prague:", "")
+ assertDescriptionLineValue(t, "Osaka:", "")
+ assertDescriptionLineValue(t, "DynamicGasLimit:", "")
+ assertDescriptionLineValue(t, "TIPUpgradeReward:", "")
+ assertDescriptionLineValue(t, "TIPUpgradePenalty:", "")
+ assertDescriptionLineValue(t, "TIPEpochHalving:", "")
+ assertDescriptionLineValue(t, "TRC21IssuerSMC:", zeroAddress0x)
+ assertDescriptionLineValue(t, "XDCXListingSMC:", zeroAddress0x)
+ assertDescriptionLineValue(t, "RelayerRegistrationSMC:", zeroAddress0x)
+ assertDescriptionLineValue(t, "LendingRegistrationSMC:", zeroAddress0x)
+}
+
+func TestGatherForksIncludesXDPoSV2SwitchBlock(t *testing.T) {
+ config := &ChainConfig{
+ HomesteadBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(1000),
+ Eip1559Block: big.NewInt(1000),
+ XDPoS: &XDPoSConfig{V2: &V2{
+ SwitchBlock: big.NewInt(1500),
+ }},
+ }
+ assert.Equal(t, []uint64{1000, 1500}, config.GatherForks())
+}
+
+func TestChainConfigStringIncludesAllFields(t *testing.T) {
+ config := &ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(2),
+ DAOForkBlock: big.NewInt(3),
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(4),
+ EIP155Block: big.NewInt(5),
+ EIP158Block: big.NewInt(6),
+ ByzantiumBlock: big.NewInt(7),
+ ConstantinopleBlock: big.NewInt(8),
+ PetersburgBlock: big.NewInt(9),
+ IstanbulBlock: big.NewInt(10),
+ BerlinBlock: big.NewInt(11),
+ LondonBlock: big.NewInt(12),
+ MergeBlock: big.NewInt(13),
+ ShanghaiBlock: big.NewInt(14),
+ Eip1559Block: big.NewInt(15),
+ CancunBlock: big.NewInt(16),
+ PragueBlock: big.NewInt(17),
+ OsakaBlock: big.NewInt(18),
+ TIP2019Block: big.NewInt(19),
+ TIPSigningBlock: big.NewInt(20),
+ TIPRandomizeBlock: big.NewInt(21),
+ TIPIncreaseMasternodesBlock: big.NewInt(22),
+ DenylistBlock: big.NewInt(23),
+ TIPNoHalvingMNRewardBlock: big.NewInt(24),
+ TIPXDCXBlock: big.NewInt(25),
+ TIPXDCXLendingBlock: big.NewInt(26),
+ TIPXDCXCancellationFeeBlock: big.NewInt(27),
+ TIPTRC21FeeBlock: big.NewInt(28),
+ TIPXDCXMinerDisableBlock: big.NewInt(29),
+ TIPXDCXReceiverDisableBlock: big.NewInt(30),
+ DynamicGasLimitBlock: big.NewInt(31),
+ TIPUpgradeRewardBlock: big.NewInt(32),
+ TIPUpgradePenaltyBlock: big.NewInt(33),
+ TIPEpochHalvingBlock: big.NewInt(34),
+ TRC21IssuerSMC: common.HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
+ XDCXListingSMC: common.HexToAddress("0xDE34dD0f536170993E8CFF639DdFfCF1A85D3E53"),
+ RelayerRegistrationSMC: common.HexToAddress("0x16c63b79f9C8784168103C0b74E6A59EC2de4a02"),
+ LendingRegistrationSMC: common.HexToAddress("0x7d761afd7ff65a79e4173897594a194e3c506e57"),
+ Ethash: new(EthashConfig),
+ Clique: &CliqueConfig{Period: 1, Epoch: 2},
+ XDPoS: &XDPoSConfig{
+ Period: 2,
+ Epoch: 900,
+ Reward: 5000,
+ RewardCheckpoint: 900,
+ Gap: 450,
+ FoundationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"),
+ V2: &V2{
+ SwitchEpoch: 1,
+ SwitchBlock: big.NewInt(900),
+ CurrentConfig: &V2Config{
+ MaxMasternodes: 18,
+ },
+ },
+ },
+ }
+
+ got := config.String()
+ assert.NotContains(t, got, "SchemaVersion:")
+
+ encoded, err := json.Marshal(config)
+ assert.NoError(t, err)
+ assert.NotContains(t, string(encoded), "schemaVersion")
+
+ for _, label := range []string{
+ "ChainID:",
+ "Homestead:",
+ "DAOFork:",
+ "DAOForkSupport:",
+ "TIP2019:",
+ "EIP150:",
+ "EIP155:",
+ "EIP158:",
+ "Byzantium:",
+ "Constantinople:",
+ "Petersburg:",
+ "Istanbul:",
+ "TIPSigning:",
+ "TIPRandomize:",
+ "TIPIncreaseMasternodes:",
+ "Denylist:",
+ "TIPNoHalvingMNReward:",
+ "TIPXDCX:",
+ "TIPXDCXLending:",
+ "TIPXDCXCancellationFee:",
+ "TIPTRC21Fee:",
+ "Berlin:",
+ "London:",
+ "Merge:",
+ "Shanghai:",
+ "TIPXDCXMinerDisable:",
+ "TIPXDCXReceiverDisable:",
+ "Eip1559:",
+ "Cancun:",
+ "Prague:",
+ "Osaka:",
+ "DynamicGasLimit:",
+ "TIPUpgradeReward:",
+ "TIPUpgradePenalty:",
+ "TIPEpochHalving:",
+ "TRC21IssuerSMC:",
+ "XDCXListingSMC:",
+ "RelayerRegistrationSMC:",
+ "LendingRegistrationSMC:",
+ "Ethash:",
+ "Clique:",
+ "XDPoS:",
+ } {
+ assert.Contains(t, got, label)
+ }
+}
+
func TestXDPoSConfigUnmarshalLegacyFoundationWalletAddr(t *testing.T) {
const raw = `{"period":2,"epoch":900,"reward":5000,"rewardCheckpoint":900,"gap":450,"foudationWalletAddr":"xdc746249c61f5832c5eed53172776b460491bdcd5c"}`
@@ -170,3 +974,23 @@ func TestXDPoSConfigUnmarshalFoundationWalletAddrPrecedence(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, common.HexToAddress("xdc92a289fe95a85c53b8d0d113cbaef0c1ec98ac65"), cfg.FoundationWalletAddr)
}
+
+func TestGetBuiltInChainConfigByHashHashOnly(t *testing.T) {
+ tests := []struct {
+ name string
+ hash common.Hash
+ want bool
+ }{
+ {name: "mainnet hash", hash: MainnetGenesisHash, want: true},
+ {name: "testnet hash", hash: TestnetGenesisHash, want: true},
+ {name: "devnet hash", hash: DevnetGenesisHash, want: true},
+ {name: "empty hash", hash: common.Hash{}, want: false},
+ {name: "random hash", hash: common.HexToHash("0x1"), want: false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.Equal(t, tt.want, GetBuiltInChainConfigByHash(tt.hash) != nil)
+ })
+ }
+}
diff --git a/params/forks/forks.go b/params/forks/forks.go
new file mode 100644
index 000000000000..b2dbcd360719
--- /dev/null
+++ b/params/forks/forks.go
@@ -0,0 +1,113 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package forks
+
+import "fmt"
+
+// Fork is a numerical identifier of specific network upgrades (forks).
+type Fork int
+
+const (
+ Frontier Fork = iota
+ FrontierThawing
+ Homestead
+ DAO
+ TIP2019
+ TangerineWhistle // a.k.a. the EIP150 fork
+ SpuriousDragon // a.k.a. the EIP155 fork
+ EIP158
+ Byzantium
+ Constantinople
+ Petersburg
+ Istanbul
+ TIPSigning
+ TIPRandomize
+ TIPIncreaseMasternodes
+ Denylist
+ TIPNoHalvingMNReward
+ TIPXDCX
+ TIPXDCXLending
+ TIPXDCXCancellationFee
+ TIPTRC21Fee
+ Berlin
+ London
+ Merge
+ Shanghai
+ Gas50x
+ XDPoSV2
+ TIPXDCXMiner
+ TIPXDCXReceiver
+ XDCxDisable
+ EIP1559
+ Cancun
+ DynamicGasLimit
+ TIPUpgradeReward
+ TIPUpgradePenalty
+ TIPEpochHalving
+ Prague
+ Osaka
+)
+
+// String implements fmt.Stringer.
+func (f Fork) String() string {
+ s, ok := forkToString[f]
+ if !ok {
+ return fmt.Sprintf("Unknown fork (%d)", f)
+ }
+ return s
+}
+
+var forkToString = map[Fork]string{
+ Frontier: "Frontier",
+ FrontierThawing: "Frontier Thawing",
+ Homestead: "Homestead",
+ DAO: "DAO",
+ TIP2019: "TIP2019",
+ TangerineWhistle: "Tangerine Whistle",
+ SpuriousDragon: "Spurious Dragon",
+ EIP158: "EIP158",
+ Byzantium: "Byzantium",
+ Constantinople: "Constantinople",
+ Petersburg: "Petersburg",
+ Istanbul: "Istanbul",
+ TIPSigning: "TIPSigning",
+ TIPRandomize: "TIPRandomize",
+ TIPIncreaseMasternodes: "TIPIncreaseMasternodes",
+ Denylist: "Denylist",
+ TIPNoHalvingMNReward: "TIPNoHalvingMNReward",
+ TIPXDCX: "TIPXDCX",
+ TIPXDCXLending: "TIPXDCXLending",
+ TIPXDCXCancellationFee: "TIPXDCXCancellationFee",
+ TIPTRC21Fee: "TIPTRC21Fee",
+ Berlin: "Berlin",
+ London: "London",
+ Merge: "Merge",
+ Shanghai: "Shanghai",
+ Gas50x: "Gas50x",
+ XDPoSV2: "XDPoS V2",
+ TIPXDCXMiner: "TIPXDCXMiner",
+ TIPXDCXReceiver: "TIPXDCXReceiver",
+ XDCxDisable: "XDCxDisable",
+ EIP1559: "EIP1559",
+ Cancun: "Cancun",
+ DynamicGasLimit: "DynamicGasLimit",
+ TIPUpgradeReward: "TIPUpgradeReward",
+ TIPUpgradePenalty: "TIPUpgradePenalty",
+ TIPEpochHalving: "TIPEpochHalving",
+ Prague: "Prague",
+ Osaka: "Osaka",
+}
diff --git a/tests/transaction_test.go b/tests/transaction_test.go
index 494181c0ddf2..98892ec19c8f 100644
--- a/tests/transaction_test.go
+++ b/tests/transaction_test.go
@@ -28,21 +28,24 @@ func TestTransaction(t *testing.T) {
txt := new(testMatcher)
txt.config(`^Homestead/`, params.ChainConfig{
- HomesteadBlock: big.NewInt(0),
+ HomesteadBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
})
txt.config(`^EIP155/`, params.ChainConfig{
- HomesteadBlock: big.NewInt(0),
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ChainID: big.NewInt(1),
+ TIPTRC21FeeBlock: big.NewInt(0),
})
txt.config(`^Byzantium/`, params.ChainConfig{
- HomesteadBlock: big.NewInt(0),
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
+ HomesteadBlock: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ TIPTRC21FeeBlock: big.NewInt(0),
})
txt.walk(t, transactionTestDir, func(t *testing.T, name string, test *TransactionTest) {
diff --git a/tests/vm_test.go b/tests/vm_test.go
index 1816d02d6022..6c2eadd484db 100644
--- a/tests/vm_test.go
+++ b/tests/vm_test.go
@@ -20,16 +20,13 @@ import (
"math/big"
"testing"
- "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/vm"
+ "github.com/XinFinOrg/XDPoSChain/params"
)
func TestVM(t *testing.T) {
- oldTIPXDCXCancellationFee := new(big.Int).Set(common.TIPXDCXCancellationFee)
- defer func() {
- common.TIPXDCXCancellationFee = oldTIPXDCXCancellationFee
- }()
- common.TIPXDCXCancellationFee = big.NewInt(100000000)
+ chainConfig := *params.MainnetChainConfig
+ chainConfig.TIPXDCXCancellationFeeBlock = big.NewInt(100000000)
vmt := new(testMatcher)
vmt.fails("^vmSystemOperationsTest.json/createNameRegistrator$", "fails without parallel execution")
@@ -39,6 +36,7 @@ func TestVM(t *testing.T) {
vmt.skipShortMode("^vmInputLimits(Light)?.json")
vmt.walk(t, vmTestDir, func(t *testing.T, name string, test *VMTest) {
+ test.chainConfig = &chainConfig
withTrace(t, test.json.Exec.GasLimit, func(vmconfig vm.Config) error {
return vmt.checkFailure(t, name, test.Run(vmconfig))
})
diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go
index 505f49c21dc6..1986fd134d64 100644
--- a/tests/vm_test_util.go
+++ b/tests/vm_test_util.go
@@ -39,7 +39,8 @@ import (
// VMTest checks EVM execution without block or transaction context.
// See https://github.com/ethereum/tests/wiki/VM-Tests for the test format specification.
type VMTest struct {
- json vmJSON
+ json vmJSON
+ chainConfig *params.ChainConfig
}
func (t *VMTest) UnmarshalJSON(data []byte) error {
@@ -148,7 +149,11 @@ func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM {
GasLimit: t.json.Env.GasLimit,
Difficulty: t.json.Env.Difficulty,
}
- evm := vm.NewEVM(context, statedb, nil, params.MainnetChainConfig, vmconfig)
+ chainConfig := t.chainConfig
+ if chainConfig == nil {
+ chainConfig = params.MainnetChainConfig
+ }
+ evm := vm.NewEVM(context, statedb, nil, chainConfig, vmconfig)
evm.SetTxContext(txContext)
return evm
}