diff --git a/pool/apollo_xlayer.go b/pool/apollo_xlayer.go index 54a8a3fac9..82af2e909b 100644 --- a/pool/apollo_xlayer.go +++ b/pool/apollo_xlayer.go @@ -20,7 +20,11 @@ type apolloConfig struct { FreeGasExAddress []string FreeGasCountPerAddr uint64 FreeGasLimit uint64 - FreeGasList []FreeGasInfo + + // for special project + EnableFreeGasList bool + FreeGasFromNameMap map[string]string // map[from]projectName + FreeGasList map[string]*FreeGasInfo // map[projectName]FreeGasInfo BlockedList []string @@ -48,8 +52,14 @@ func (c *apolloConfig) setFreeGasList(freeGasList []FreeGasInfo) { if c == nil || !c.EnableApollo { return } - c.FreeGasList = make([]FreeGasInfo, len(freeGasList)) - copy(c.FreeGasList, freeGasList) + c.FreeGasFromNameMap = make(map[string]string) + c.FreeGasList = make(map[string]*FreeGasInfo, len(freeGasList)) + for _, info := range freeGasList { + for _, from := range info.FromList { + c.FreeGasFromNameMap[from] = info.Name + } + c.FreeGasList[info.Name] = &info + } } func (c *apolloConfig) setFreeGasAddresses(freeGasAddrs []string) { @@ -104,6 +114,7 @@ func UpdateConfig(apolloConfig Config) { getApolloConfig().setFreeGasExAddresses(apolloConfig.FreeGasExAddress) getApolloConfig().FreeGasCountPerAddr = apolloConfig.FreeGasCountPerAddr getApolloConfig().FreeGasLimit = apolloConfig.FreeGasLimit + getApolloConfig().EnableFreeGasList = apolloConfig.EnableFreeGasList getApolloConfig().setFreeGasList(apolloConfig.FreeGasList) getApolloConfig().Unlock() @@ -213,13 +224,32 @@ func isBlockedAddress(localBlockedList []string, address common.Address) bool { return contains(localBlockedList, address) } +// GetEnableSpecialFreeGasList returns enable flag of FreeGasList +func GetEnableSpecialFreeGasList(enableFreeGasList bool) bool { + if getApolloConfig().enable() { + getApolloConfig().RLock() + defer getApolloConfig().RUnlock() + return getApolloConfig().EnableFreeGasList + } + return enableFreeGasList +} + // GetSpecialFreeGasList returns the special project in XLayer for free gas -func GetSpecialFreeGasList(freeGasList []FreeGasInfo) []FreeGasInfo { +func GetSpecialFreeGasList(freeGasList []FreeGasInfo) (map[string]string, map[string]*FreeGasInfo) { if getApolloConfig().enable() { getApolloConfig().RLock() defer getApolloConfig().RUnlock() - return getApolloConfig().FreeGasList + return getApolloConfig().FreeGasFromNameMap, getApolloConfig().FreeGasList + } + + freeGasFromNameMap := make(map[string]string) + freeGasMap := make(map[string]*FreeGasInfo, len(freeGasList)) + for _, info := range freeGasList { + for _, from := range info.FromList { + freeGasFromNameMap[from] = info.Name + } + freeGasMap[info.Name] = &info } - return freeGasList + return freeGasFromNameMap, freeGasMap } diff --git a/pool/config.go b/pool/config.go index 0eca248db0..a7cd61baa1 100644 --- a/pool/config.go +++ b/pool/config.go @@ -71,16 +71,19 @@ type Config struct { FreeGasCountPerAddr uint64 `mapstructure:"FreeGasCountPerAddr"` // FreeGasLimit is the max gas allowed use to do a free gas tx FreeGasLimit uint64 `mapstructure:"FreeGasLimit"` + // EnableFreeGasList enable the special project of XLayer for free gas + EnableFreeGasList bool `mapstructure:"EnableFreeGasList"` // FreeGasList is the special project of XLayer FreeGasList []FreeGasInfo `mapstructure:"FreeGasList"` } // FreeGasInfo contains the details for what tx should be free type FreeGasInfo struct { - From string `mapstructure:"From"` - To string `mapstructure:"To"` - MethodSig string `mapstructure:"MethodSig"` - GasPriceMultiple float64 `mapstructure:"GasPriceMultiple"` + Name string `mapstructure:"Name"` + FromList []string `mapstructure:"FromList"` + ToList []string `mapstructure:"ToList"` + MethodSigs []string `mapstructure:"MethodSigs"` + GasPriceMultiple float64 `mapstructure:"GasPriceMultiple"` } // EffectiveGasPriceCfg contains the configuration properties for the effective gas price diff --git a/pool/pool_xlayer.go b/pool/pool_xlayer.go index de1cd3ce7f..3baabba02f 100644 --- a/pool/pool_xlayer.go +++ b/pool/pool_xlayer.go @@ -40,6 +40,15 @@ func contains(s []string, ele common.Address) bool { return false } +func containsMethod(data string, methods []string) bool { + for _, m := range methods { + if strings.HasPrefix(data, m) { + return true + } + } + return false +} + // StartRefreshingWhiteAddressesPeriodically will make this instance of the pool // to check periodically(accordingly to the configuration) for updates regarding // the white address and update the in memory blocked addresses @@ -113,17 +122,23 @@ func (p *Pool) GetDynamicGasPrice() *big.Int { } func (p *Pool) checkFreeGp(ctx context.Context, poolTx Transaction, from common.Address) (bool, error) { - if isFreeGasAddress(p.cfg.FreeGasAddress, from) && poolTx.IsClaims { // claim tx + // claim tx + if isFreeGasAddress(p.cfg.FreeGasAddress, from) && poolTx.IsClaims { return true, nil } - freeGpList := GetSpecialFreeGasList(p.cfg.FreeGasList) - for _, info := range freeGpList { - if from.String() == info.From { - if poolTx.To().String() == info.To && strings.HasPrefix("0x"+common.Bytes2Hex(poolTx.Data()), info.MethodSig) { - return true, nil - } + + // special project + if GetEnableSpecialFreeGasList(p.cfg.EnableFreeGasList) { + fromToName, freeGpList := GetSpecialFreeGasList(p.cfg.FreeGasList) + info := freeGpList[fromToName[from.String()]] + if info != nil && + contains(info.ToList, *poolTx.To()) && + containsMethod("0x"+common.Bytes2Hex(poolTx.Data()), info.MethodSigs) { + return true, nil } } + + // new bridge address if getEnableFreeGasByNonce(p.cfg.EnableFreeGasByNonce) && poolTx.GasPrice().Cmp(big.NewInt(0)) == 0 { // free-gas tx by count isFreeAddr, err := p.storage.IsFreeGasAddr(ctx, from) if err != nil { diff --git a/sequencer/sequencer_xlayer.go b/sequencer/sequencer_xlayer.go index 18d451e286..5f525611f8 100644 --- a/sequencer/sequencer_xlayer.go +++ b/sequencer/sequencer_xlayer.go @@ -15,6 +15,24 @@ import ( var countinterval = 10 +func contains(s []string, ele common.Address) bool { + for _, e := range s { + if common.HexToAddress(e) == ele { + return true + } + } + return false +} + +func containsMethod(data string, methods []string) bool { + for _, m := range methods { + if strings.HasPrefix(data, m) { + return true + } + } + return false +} + func (s *Sequencer) countPendingTx() { for { <-time.After(time.Second * time.Duration(countinterval)) @@ -49,14 +67,15 @@ func (s *Sequencer) checkFreeGas(tx pool.Transaction, txTracker *TxTracker) (fre claimTx = true } - // special project of XLayer - freeGpList := pool.GetSpecialFreeGasList(s.poolCfg.FreeGasList) - for _, info := range freeGpList { - if txTracker.From.String() == info.From { - if tx.To().String() == info.To && strings.HasPrefix("0x"+common.Bytes2Hex(tx.Data()), info.MethodSig) { - gpMul = info.GasPriceMultiple - return - } + // check if tx is from special project + if pool.GetEnableSpecialFreeGasList(s.poolCfg.EnableFreeGasList) { + fromToName, freeGpList := pool.GetSpecialFreeGasList(s.poolCfg.FreeGasList) + info := freeGpList[fromToName[txTracker.FromStr]] + if info != nil && + contains(info.ToList, *tx.To()) && + containsMethod("0x"+common.Bytes2Hex(tx.Data()), info.MethodSigs) { + gpMul = info.GasPriceMultiple + return } }