diff --git a/.gitignore b/.gitignore index b118fd8..3689fe9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ -target/classes/org/tron/trongrid/ContractEventTriggerEntity.class -target/classes/org/tron/trongrid/InternalTransactionPojo.class +target/* +.idea/* +troneventquery.iml +.classpath +.factorypath +.settings/* +.vscode/* diff --git a/README.md b/README.md index 1667b16..69943ce 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,10 @@ Make sure the relative path of config.conf and troneventquery jar. The config.co - troneventquery/insertIndex.sh is used to setup mongodb index to speedup query. (make sure run insertIndex before create collecions) + ## Delete expire data +- troneventquery/deleteData.sh is used to delete expire data +- using crontable delete regularly mongodb expire data(if not delete, the database will be too big) + ## What is the main HTTP service? baseUrl: https://api.tronex.io @@ -170,7 +174,6 @@ limit: each page size, default is 25 sort: sort Field, default is sort by timeStamp descending order start: start page, default is 1 -Note: if developers wants to check whether this event is confirmed or not, they could check the blocknumber is small than the solidified block number(get from url https://api.tronex.io/blocks/latestblockNum). If it is smaller than block number, it is conformed Example: https://api.tronex.io/events/confirmed?since=1544483426749&limit=1&start=1&sort=timeStamp ``` @@ -197,7 +200,7 @@ block: block number, block number >= block will be shown Example: https://api.tronex.io/blocks?limit=1&sort=timeStamp&start=0&block=0 ``` -Function: get latest solidified block number +Function: get latest block number ``` subpath: $baseUrl/blocks/latestSolidifiedBlockNumber @@ -206,3 +209,73 @@ none Example: https://api.tronex.io/blocks/latestSolidifiedBlockNumber ``` +Function: get contract log list +``` +subpath: $baseUrl/contractlogs + +parameters +limit: each page size, default is 25 +sort: sort Field, default is sort by timeStamp descending order +start: start page, default is 1 +block: block number, block number >= block will be shown + +Example: https://api.tronex.io/contractlogs +``` +Function: get contract log list based on transactionId +``` +subpath: $baseUrl/contractlogs/transaction/{transactionId} + +parameters +transactionId + +Example: https://api.tronex.io/contractlogs/transaction/{transactionId} +``` +Function: post abi string and get contract log list based on transactionId(release on 3.6) +``` +subpath: $baseUrl/contract/transaction/{transactionId} + +parameters +transactionId +body: +abi: user self upload abi + +Example: https://api.tronex.io/contract/transaction/{transactionId} +``` +Function: get contract log list based on contractAddress +``` +subpath: $baseUrl/contractlogs/contract/{contractAddress} + +parameters +contractAddress + +Example: https://api.tronex.io/contractlogs/contract/{contractAddress} +``` +Function: post abi string and get contract log list based on contractAddress(release on 3.6) +``` +subpath: $baseUrl/contract/contractAddress/{contractAddress} + +parameters +contractAddress +abi: user self upload abi + +Example: https://api.tronex.io/contract/contractAddress/{contractAddress} +``` +Function: get contract log list based on uniqueId +``` +subpath: $baseUrl/contractlogs/uniqueId/{uniqueId} + +parameters +uniqueId + +Example: https://api.tronex.io/contractlogs/uniqueId/{uniqueId} +``` +Function: post abi string and get contract log list based on uniqueId(release on 3.6) +``` +subpath: $baseUrl/contract/uniqueId/{uniqueId} + +parameters +uniqueId +abi: user self upload abi + +Example: https://api.tronex.io/contract/uniqueId/{uniqueId} +``` diff --git a/config.conf b/config.conf index f90c3fc..0214bf4 100644 --- a/config.conf +++ b/config.conf @@ -1,9 +1,9 @@ -mongo.host=47.90.245.68 -mongo.port=27017 +mongo.host=127.0.0.1 +mongo.port=18883 mongo.dbname=eventlog mongo.username=tron mongo.password=123456 -mongo.connectionsPerHost=8 -mongo.threadsAllowedToBlockForConnectionMultiplier=4 +mongo.connectionsPerHost=200 +mongo.threadsAllowedToBlockForConnectionMultiplier=10 mongo.deadline=10 diff --git a/deploy.sh b/deploy.sh index dbd7ea4..85f5d98 100755 --- a/deploy.sh +++ b/deploy.sh @@ -10,6 +10,12 @@ while true; do break fi done -nohup java -jar target/troneventquery-1.0.0-SNAPSHOT.jar 2>&1 & +total=`cat /proc/meminfo |grep MemTotal |awk -F ' ' '{print $2}'` +xmx=`echo "$total/1024/1024*0.6" | bc |awk -F. '{print $1"g"}'` +logtime=`date +%Y-%m-%d_%H-%M-%S` + nohup java -Xmx$xmx -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xloggc:./gc.log\ + -XX:+PrintGCDateStamps -XX:+CMSParallelRemarkEnabled -XX:ReservedCodeCacheSize=256m\ + -XX:+CMSScavengeBeforeRemark -jar target/troneventquery-1.0.0-SNAPSHOT.jar >> query.log 2>&1 & + sleep 10 echo "ok!" diff --git a/pom.xml b/pom.xml index 08fc1c2..99b7ca4 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ com.alibaba fastjson - 1.2.49 + 2.0.16 @@ -82,17 +82,16 @@ com.google.protobuf protobuf-java - 3.5.1 + 3.16.1 com.google.guava guava - 24.1-jre + [30.0-jre,) - diff --git a/src/main/java/org/tron/common/crypto/Crypto.java b/src/main/java/org/tron/common/crypto/Crypto.java new file mode 100644 index 0000000..21784b7 --- /dev/null +++ b/src/main/java/org/tron/common/crypto/Crypto.java @@ -0,0 +1,83 @@ +package org.tron.common.crypto; +import static org.tron.common.utils.LogConfig.LOG; + +import java.util.regex.Pattern; + +public class Crypto { + + private final static long SECRET_KEY = 5658116; + private final static String CONVERT_KEY = "DeCATbJIzM"; + private final static String CONFUSED_WORDS_KEY = "FxYNgq"; + private final static int LEN_KEY = 32; + + + static public String encrypt(String str){ + Long time = new Long(157551410); + if(!isNumber(str)){ + LOG.info("not number"); + return null; + } + + long number = Long.parseLong(str); + long newNumber = (number + time) * SECRET_KEY; + String[] numArr = String.valueOf(newNumber).split(""); + String[] initArr = CONVERT_KEY.split(""); + int len = numArr.length; + StringBuffer buffer = new StringBuffer(); + + for(int i = 0; i < len; i++){ + int inx = Integer.parseInt(numArr[i]); + buffer.append(initArr[inx]); + } + + String[] cwkArr = CONFUSED_WORDS_KEY.split(""); + if(len < LEN_KEY){ + int l = LEN_KEY - len; + for(int i = 0; i < l; i++){ + int index = (int)(Math.random()*buffer.length()); + int inx = (int)(Math.random()*(CONFUSED_WORDS_KEY.length())); + buffer.insert(index,cwkArr[inx]); + } + } + String result = buffer.toString(); + return result; + } + + public static int decrypt(String str){ + Long time = new Long(157551410); + if(null == str || "".equals(str)){ + return 0; + } + int l = CONFUSED_WORDS_KEY.length(); + String[] cwkArr = CONFUSED_WORDS_KEY.split(""); + for(int i = 0; i < l; i++){ + str = str.replaceAll(cwkArr[i],""); + } + String[] initArr = str.split(""); + int len = initArr.length; + StringBuffer result = new StringBuffer(); + for(int i = 0; i < len; i++ ){ + int k = CONVERT_KEY.indexOf(initArr[i]); + if(k == -1){ + return 0; + } + result.append(k); + } + Long number; + try { + long total = Long.parseLong(result.toString()); + long sum = total/SECRET_KEY; + number = sum - time; + } catch (NumberFormatException e) { + e.printStackTrace(); + return 0; + } + return number.intValue(); + } + + public static boolean isNumber(String value) { + String pattern = "^[0-9]*[1-9][0-9]*$"; + boolean isMatch = Pattern.matches(pattern, value); + return isMatch; + } +} diff --git a/src/main/java/org/tron/common/crypto/Hash.java b/src/main/java/org/tron/common/crypto/Hash.java index 6421c33..0a1cfc0 100644 --- a/src/main/java/org/tron/common/crypto/Hash.java +++ b/src/main/java/org/tron/common/crypto/Hash.java @@ -18,6 +18,8 @@ package org.tron.common.crypto; +import static org.tron.common.utils.LogConfig.LOG; + import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Provider; @@ -25,7 +27,6 @@ import lombok.extern.slf4j.Slf4j; import org.tron.common.crypto.jce.TronCastleProvider; -@Slf4j(topic = "crypto") public class Hash { private static final Provider CRYPTO_PROVIDER; @@ -48,7 +49,7 @@ public static byte[] sha3(byte[] input) { digest.update(input); return digest.digest(); } catch (NoSuchAlgorithmException e) { - log.error("Can't find such algorithm", e); + LOG.error("Can't find such algorithm", e); throw new RuntimeException(e); } } diff --git a/src/main/java/org/tron/common/utils/ByteArray.java b/src/main/java/org/tron/common/utils/ByteArray.java index f2722be..52b5ccc 100644 --- a/src/main/java/org/tron/common/utils/ByteArray.java +++ b/src/main/java/org/tron/common/utils/ByteArray.java @@ -18,6 +18,8 @@ package org.tron.common.utils; +import static org.tron.common.utils.LogConfig.LOG; + import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; import java.io.ByteArrayOutputStream; @@ -29,7 +31,6 @@ import org.apache.commons.lang3.StringUtils; import org.spongycastle.util.encoders.Hex; -@Slf4j(topic = "utils") public class ByteArray { public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; @@ -101,7 +102,7 @@ public static byte[] fromObject(Object obj) { objectOutputStream.flush(); bytes = byteArrayOutputStream.toByteArray(); } catch (IOException e) { - log.error("objectToByteArray failed: " + e.getMessage(), e); + LOG.error("objectToByteArray failed: " + e.getMessage(), e); } return bytes; } diff --git a/src/main/java/org/tron/common/utils/LogConfig.java b/src/main/java/org/tron/common/utils/LogConfig.java new file mode 100644 index 0000000..c37f415 --- /dev/null +++ b/src/main/java/org/tron/common/utils/LogConfig.java @@ -0,0 +1,10 @@ +package org.tron.common.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LogConfig { + public static final Logger LOG = LoggerFactory.getLogger(LogConfig.class); +} \ No newline at end of file diff --git a/src/main/java/org/tron/core/Wallet.java b/src/main/java/org/tron/core/Wallet.java index 862692a..431e29b 100755 --- a/src/main/java/org/tron/core/Wallet.java +++ b/src/main/java/org/tron/core/Wallet.java @@ -49,7 +49,7 @@ public static String encode58Check(byte[] input) { return Base58.encode(inputCheck); } - private static byte[] decode58Check(String input) { + public static byte[] decode58Check(String input) { byte[] decodeCheck = Base58.decode(input); if (decodeCheck.length <= 4) { return null; diff --git a/src/main/java/org/tron/trongeventquery/TronEventApplication.java b/src/main/java/org/tron/trongeventquery/TronEventApplication.java index c436886..6fe27e1 100644 --- a/src/main/java/org/tron/trongeventquery/TronEventApplication.java +++ b/src/main/java/org/tron/trongeventquery/TronEventApplication.java @@ -1,5 +1,8 @@ package org.tron.trongeventquery; +import static org.tron.common.utils.LogConfig.LOG; +import static org.tron.trongeventquery.contractevents.ContractEventController.isRunRePushThread; + import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.MongoCredential; @@ -14,37 +17,23 @@ import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import org.springframework.web.filter.CorsFilter; + @SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) +@ServletComponentScan("org.tron.trongeventquery.filter") //Scan Filter @PropertySource(value = {"file:./config.conf"}, ignoreResourceNotFound = true) public class TronEventApplication { public static void main(String[] args) { SpringApplication.run(TronEventApplication.class, args); + shutdown(); } - - @Bean - public FilterRegistrationBean corsFilter() { - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - CorsConfiguration config = new CorsConfiguration(); - config.setAllowCredentials(true); - config.addAllowedOrigin("*"); - config.addAllowedHeader("*"); - config.addAllowedMethod("*"); - source.registerCorsConfiguration("/**", config); - FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); - bean.setOrder(0); - return bean; - } - + @Bean public MongoTemplate mongoTemplate( @Value("${mongo.host}")String mongodbIp, @Value("${mongo.dbname}")String mongodbDbName, @@ -82,4 +71,11 @@ public void customize(Connector connector) { }); return factory; } + + public static void shutdown() { + Runnable stopThread = + () -> isRunRePushThread.set(false); + LOG.info("********register application shutdown hook********"); + Runtime.getRuntime().addShutdownHook(new Thread(stopThread)); + } } diff --git a/src/main/java/org/tron/trongeventquery/contractevents/ContractEventController.java b/src/main/java/org/tron/trongeventquery/contractevents/ContractEventController.java index d01dc80..89521f9 100644 --- a/src/main/java/org/tron/trongeventquery/contractevents/ContractEventController.java +++ b/src/main/java/org/tron/trongeventquery/contractevents/ContractEventController.java @@ -1,5 +1,9 @@ package org.tron.trongeventquery.contractevents; + +import static org.tron.common.utils.LogConfig.LOG; +import static org.tron.core.Wallet.decode58Check; + import com.alibaba.fastjson.JSONObject; import java.util.ArrayList; import java.util.HashMap; @@ -7,22 +11,43 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import org.apache.commons.lang3.StringUtils; +import org.spongycastle.util.Strings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.tron.common.crypto.Crypto; +import org.tron.common.utils.ByteArray; import org.tron.trongeventquery.query.QueryFactory; +import org.tron.trongeventquery.response.Response; +import org.tron.trongeventquery.solidityevents.SolidityTriggerEntity; @RestController +@Component public class ContractEventController { + public static final String ADD_PRE_FIX_STRING_MAINNET = "41"; + private static final int RETURN_ALL_EVENTS = 0; + private static final int RETURN_ONLY_CONFIRMED_EVENTS = 1; + private static final int RETURN_ONLY_UNCONFIRMED_EVENTS = 2; + private static final int CONFILICTING_PARAMETERS = -1; + + @Autowired MongoTemplate mongoTemplate; + public static AtomicBoolean isRunRePushThread = new AtomicBoolean(true); + public static AtomicLong latestSolidifiedBlockNumber = new AtomicLong(0); @RequestMapping(method = RequestMethod.GET, value = "/healthcheck") public String healthCheck() { @@ -37,7 +62,6 @@ public List events( @RequestParam(value = "sort", required = false, defaultValue = "-timeStamp") String sort, @RequestParam(value = "start", required = false, defaultValue = "0") int start ) { - QueryFactory query = new QueryFactory(); if (blocknum != -1) { query.setBlockNumGte(blocknum); @@ -96,7 +120,7 @@ public List verifyEvents( long latestSolidifiedBlockNumber = contractEventTriggerEntityList.get(0).getLatestSolidifiedBlockNumber(); query = new QueryFactory(); - query.setBlockNumSmall(latestSolidifiedBlockNumber); + query.setBlockNumLte(latestSolidifiedBlockNumber); query.setTimestampGreaterEqual(timestamp); query.setRemovedEqual(false); query.setPageniate(QueryFactory.setPagniateVariable(start, limit, sort)); @@ -112,54 +136,7 @@ public List findOneByTransaction(@PathVariable Strin query.setTransactionIdEqual(transactionId); List queryResult = mongoTemplate.find(query.getQuery(), ContractEventTriggerEntity.class); - return queryResult; - } - - // get event list - @RequestMapping(method = RequestMethod.GET, value = "/events/{contractAddress}") - public List findEventsListByContractAddress( - @PathVariable String contractAddress, - @RequestParam(value = "limit", required = false, defaultValue = "25") int limit, - @RequestParam(value = "sort", required = false, defaultValue = "-timeStamp") String sort, - @RequestParam(value = "start", required = false, defaultValue = "0") int start, - @RequestParam(value = "block", required = false, defaultValue = "-1") long blocknum, - @RequestParam(value = "since", required = false, defaultValue = "0") long timestamp - ) { - - QueryFactory query = new QueryFactory(); - if (blocknum != -1) { - query.setBlockNumGte(blocknum); - } - query.setContractAddress(contractAddress); - query.setTimestampGreaterEqual(timestamp); - query.setPageniate(this.setPagniateVariable(limit, sort, start)); - List result = mongoTemplate.find(query.getQuery(), - ContractEventTriggerEntity.class); - - List array = new ArrayList<>(); - for (ContractEventTriggerEntity p : result) { - Map map = new HashMap(); - map.put("transactionId", p.getTransactionId()); - map.put("blockNumber", p.getBlockNumber()); - map.put("timeStamp", p.getTimeStamp()); - map.put("eventSignatureFull", p.getEventSignatureFull()); - map.put("eventName", p.getEventName()); - map.put("contractAddress", p.getContractAddress()); - int i = 0; - Map dataMap = p.getDataMap(); - Map topicMap = p.getTopicMap(); - for (String topic : topicMap.keySet()) { - dataMap.put(topic, topicMap.get(topic)); - } - - while (dataMap.containsKey(String.valueOf(i))) { - map.put(String.valueOf(i), dataMap.get(String.valueOf(i))); - i++; - } - array.add(new JSONObject(map)); - } - - return array; + return queryResult; } @RequestMapping(method = RequestMethod.GET, @@ -228,7 +205,6 @@ public List filterevent( } query.setPageniate(this.setPagniateVariable(limit, sort, start)); - System.out.println(query.toString()); List result = mongoTemplate.find(query.getQuery(), ContractEventTriggerEntity.class); return result; @@ -279,8 +255,390 @@ private Pageable setPagniateVariable(int limit, String sort, int start) { int page = start; int pageSize = limit; - return QueryFactory.make_pagination(Math.max(0,page - 1),Math.min(200,pageSize),sort); + return QueryFactory.make_pagination(Math.max(0,page - 1), Math.min(200,pageSize), sort); + + } + + // get event list + @RequestMapping(method = RequestMethod.GET, value = "/events/{contractAddress}") + public List findEventsListByContractAddress( + @PathVariable String contractAddress, + @RequestParam(value = "limit", required = false, defaultValue = "25") int limit, + @RequestParam(value = "sort", required = false, defaultValue = "-timeStamp") String sort, + @RequestParam(value = "start", required = false, defaultValue = "0") int start, + @RequestParam(value = "block", required = false, defaultValue = "-1") long blocknum, + @RequestParam(value = "since", required = false, defaultValue = "0") long timestamp + ) { + + QueryFactory query = new QueryFactory(); + if (blocknum != -1) { + query.setBlockNumGte(blocknum); + } + query.setContractAddress(contractAddress); + query.setTimestampGreaterEqual(timestamp); + query.setPageniate(this.setPagniateVariable(limit, sort, start)); + List result = mongoTemplate.find(query.getQuery(), + ContractEventTriggerEntity.class); + + List array = new ArrayList<>(); + for (ContractEventTriggerEntity p : result) { + Map map = new HashMap(); + map.put("transactionId", p.getTransactionId()); + map.put("blockNumber", p.getBlockNumber()); + map.put("timeStamp", p.getTimeStamp()); + map.put("eventSignatureFull", p.getEventSignatureFull()); + map.put("eventName", p.getEventName()); + map.put("contractAddress", p.getContractAddress()); + int i = 0; + Map dataMap = p.getDataMap(); + Map topicMap = p.getTopicMap(); + for (String topic : topicMap.keySet()) { + dataMap.put(topic, topicMap.get(topic)); + } + + while (dataMap.containsKey(String.valueOf(i))) { + map.put(String.valueOf(i), dataMap.get(String.valueOf(i))); + i++; + } + array.add(new JSONObject(map)); + } + return array; } + // for tron web + + @RequestMapping(method = RequestMethod.GET, value = "/event/transaction/{transactionId}") + public List findOneByTransactionTronGri (@PathVariable String transactionId) { + + QueryFactory query = new QueryFactory(); + query.setTransactionIdEqual(transactionId); + List queryResult = mongoTemplate.find(query.getQuery(), + ContractEventTriggerEntity.class); + + List array = new ArrayList<>(); + for (ContractEventTriggerEntity p : queryResult) { + Map map = new HashMap(); + map.put("transaction_id", p.getTransactionId()); + map.put("block_timestamp", p.getTimeStamp()); + map.put("block_number", p.getBlockNumber()); + map.put("result_type", getResultType(p.getEventSignatureFull(), p.getEventName())); + map.put("result", getResult(p.getEventSignatureFull(), p.getEventName(), p.getTopicMap(), p.getDataMap())); + map.put("event_index", getIndex(p.getUniqueId())); + map.put("event_name", p.getEventName()); + map.put("contract_address", p.getContractAddress()); + map.put("caller_contract_address", p.getOriginAddress()); + if (p.getBlockNumber() > latestSolidifiedBlockNumber.get()) { + map.put("_unconfirmed", true); + } + + array.add(new JSONObject(map)); + } + + return array; + } + + // get event list + @RequestMapping(method = RequestMethod.GET, value = "/event/contract/{contractAddress}") + public Object findEventsByContractAddressTronGrid ( + @PathVariable String contractAddress, + @RequestParam(value = "size", required = false, defaultValue = "20") int limit, + @RequestParam(value = "sort", required = false, defaultValue = "-timeStamp") String sort, + @RequestParam(value = "start", required = false, defaultValue = "0") int start, + @RequestParam(value = "since", required = false, defaultValue = "0") long timestamp, + @RequestParam(value = "fromTimestamp", required = false, defaultValue = "0") long fromTimestamp, + @RequestParam(value = "fingerprint", required = false, defaultValue = "") String fingerprint, + @RequestParam(value = "onlyConfirmed", required = false, defaultValue = "") String onlyConfirmed, + @RequestParam(value = "onlyUnconfirmed", required = false, defaultValue = "") String onlyUnconfirmed) { + + if (sort.contains("block_timestamp")) { + sort = sort.replace("block_timestamp", "timeStamp"); + } + if (fromTimestamp > 0) { + timestamp = fromTimestamp; + } + + if (fingerprint.length() != 0) { + start = Crypto.decrypt(fingerprint) > 0 ? Crypto.decrypt(fingerprint) : 0; + } + + QueryFactory query = new QueryFactory(); + + int confirm = needConfirmed(onlyConfirmed, onlyUnconfirmed); + if (confirm == CONFILICTING_PARAMETERS) { + return new Response(false, "Conflicting parameters passed.").toJSONObject(); + } + if (confirm == RETURN_ONLY_CONFIRMED_EVENTS) { + query.setBlockNumLte(latestSolidifiedBlockNumber.get()); + } else if (confirm == RETURN_ONLY_UNCONFIRMED_EVENTS) { + query.setBlockNumGt(latestSolidifiedBlockNumber.get()); + } + + query.setContractAddress(contractAddress); + query.setTimestampGreaterEqual(timestamp); + query.setPageniate(this.setPagniateVariable(limit, sort, start)); + List result = mongoTemplate.find(query.getQuery(), + ContractEventTriggerEntity.class); + + List array = new ArrayList<>(); + int count = 1; + for (ContractEventTriggerEntity p : result) { + Map map = new HashMap(); + map.put("transaction_id", p.getTransactionId()); + map.put("block_timestamp", p.getTimeStamp()); + map.put("block_number", p.getBlockNumber()); + map.put("result_type", getResultType(p.getEventSignatureFull(), p.getEventName())); + map.put("result", getResult(p.getEventSignatureFull(), p.getEventName(), p.getTopicMap(), p.getDataMap())); + map.put("event_index", getIndex(p.getUniqueId())); + map.put("event_name", p.getEventName()); + map.put("contract_address", p.getContractAddress()); + map.put("caller_contract_address", p.getOriginAddress()); + if (p.getBlockNumber() > latestSolidifiedBlockNumber.get()) { + map.put("_unconfirmed", true); + } + + if (count++ == result.size()) { + map.put("_fingerprint", Crypto.encrypt(String.format("%d", start + 1))); + } + array.add(new JSONObject(map)); + } + + return array; + } + + // get event list + @RequestMapping(method = RequestMethod.GET, value = "/event/contract/{contractAddress}/{eventName}") + public Object findEventsByContractAddressAndEventNameTronGrid ( + @PathVariable String contractAddress, + @PathVariable String eventName, + @RequestParam(value = "size", required = false, defaultValue = "20") int limit, + @RequestParam(value = "sort", required = false, defaultValue = "-timeStamp") String sort, + @RequestParam(value = "start", required = false, defaultValue = "0") int start, + @RequestParam(value = "since", required = false, defaultValue = "0") long timestamp, + @RequestParam(value = "fromTimestamp", required = false, defaultValue = "0") long fromTimestamp, + @RequestParam(value = "fingerprint", required = false, defaultValue = "") String fingerprint, + @RequestParam(value = "onlyConfirmed", required = false, defaultValue = "") String onlyConfirmed, + @RequestParam(value = "onlyUnconfirmed", required = false, defaultValue = "") String onlyUnconfirmed + ) { + if (sort.contains("block_timestamp")) { + sort = sort.replace("block_timestamp", "timeStamp"); + } + if (fromTimestamp > 0) { + timestamp = fromTimestamp; + } + + if (fingerprint.length() != 0) { + start = Crypto.decrypt(fingerprint) > 0 ? Crypto.decrypt(fingerprint) : 0; + } + + + QueryFactory query = new QueryFactory(); + int confirm = needConfirmed(onlyConfirmed, onlyUnconfirmed); + if (confirm == CONFILICTING_PARAMETERS) { + return new Response(false, "Conflicting parameters passed.").toJSONObject(); + } + if (confirm == RETURN_ONLY_CONFIRMED_EVENTS) { + query.setBlockNumLte(latestSolidifiedBlockNumber.get()); + } else if (confirm == RETURN_ONLY_UNCONFIRMED_EVENTS) { + query.setBlockNumGt(latestSolidifiedBlockNumber.get()); + } + + query.setContractAddress(contractAddress); + query.setEventName(eventName); + + query.setTimestampGreaterEqual(timestamp); + query.setPageniate(this.setPagniateVariable(limit, sort, start)); + List result = mongoTemplate.find(query.getQuery(), + ContractEventTriggerEntity.class); + + List array = new ArrayList<>(); + int count = 1; + for (ContractEventTriggerEntity p : result) { + Map map = new HashMap(); + map.put("transaction_id", p.getTransactionId()); + map.put("block_timestamp", p.getTimeStamp()); + map.put("block_number", p.getBlockNumber()); + map.put("result_type", getResultType(p.getEventSignatureFull(), p.getEventName())); + map.put("result", getResult(p.getEventSignatureFull(), p.getEventName(), p.getTopicMap(), p.getDataMap())); + map.put("event_index", getIndex(p.getUniqueId())); + map.put("event_name", p.getEventName()); + map.put("contract_address", p.getContractAddress()); + map.put("caller_contract_address", p.getOriginAddress()); + if (p.getBlockNumber() > latestSolidifiedBlockNumber.get()) { + map.put("_unconfirmed", true); + } + + if (count++ == result.size()) { + map.put("_fingerprint", Crypto.encrypt(String.format("%d", start + 1))); + } + array.add(new JSONObject(map)); + } + + return array; + } + + @RequestMapping(method = RequestMethod.GET, value = "/event/contract/latestSolidifiedBlockNum") + public Object findLatestSolidifiedBlockNum() { + return latestSolidifiedBlockNumber.get(); + } + + // get event list + @RequestMapping(method = RequestMethod.GET, value = "/event/contract/{contractAddress}/{eventName}/{blockNumber}") + public List findEventsByContractAddressAndEventNameAndBlockNumTronGrid ( + @PathVariable String contractAddress, + @PathVariable String eventName, + @PathVariable String blockNumber, + @RequestParam(value = "size", required = false, defaultValue = "20") int limit, + @RequestParam(value = "sort", required = false, defaultValue = "-timeStamp") String sort, + @RequestParam(value = "start", required = false, defaultValue = "0") int start, + @RequestParam(value = "since", required = false, defaultValue = "0") long timestamp, + @RequestParam(value = "fromTimestamp", required = false, defaultValue = "0") long fromTimestamp, + @RequestParam(value = "fingerprint", required = false, defaultValue = "") String fingerprint + ) { + if (sort.contains("block_timestamp")) { + sort = sort.replace("block_timestamp", "timeStamp"); + } + + if (fromTimestamp > 0) { + timestamp = fromTimestamp; + } + + if (fingerprint.length() != 0) { + start = Crypto.decrypt(fingerprint) > 0 ? Crypto.decrypt(fingerprint) : 0; + } + + QueryFactory query = new QueryFactory(); + if (blockNumber.equalsIgnoreCase("latest")) { + query.setBlockNumGte(latestSolidifiedBlockNumber.get()); + } else { + query.setBlockNum(Long.parseLong(blockNumber)); + } + + + query.setContractAddress(contractAddress); + query.setEventName(eventName); + query.setTimestampGreaterEqual(timestamp); + query.setPageniate(this.setPagniateVariable(limit, sort, start)); + List result = mongoTemplate.find(query.getQuery(), + ContractEventTriggerEntity.class); + + List array = new ArrayList<>(); + int count = 1; + for (ContractEventTriggerEntity p : result) { + Map map = new HashMap(); + map.put("transaction_id", p.getTransactionId()); + map.put("block_timestamp", p.getTimeStamp()); + map.put("block_number", p.getBlockNumber()); + map.put("result_type", getResultType(p.getEventSignatureFull(), p.getEventName())); + map.put("result", getResult(p.getEventSignatureFull(), p.getEventName(), p.getTopicMap(), p.getDataMap())); + map.put("event_index", getIndex(p.getUniqueId())); + map.put("event_name", p.getEventName()); + map.put("contract_address", p.getContractAddress()); + map.put("caller_contract_address", p.getOriginAddress()); + if (p.getBlockNumber() > latestSolidifiedBlockNumber.get()) { + map.put("_unconfirmed", true); + } + + if (count++ == result.size()) { + map.put("_fingerprint", Crypto.encrypt(String.format("%d", start + 1))); + } + array.add(new JSONObject(map)); + } + + return array; + } + + JSONObject getResultType(String fullName, String eventSignature) { + int num = eventSignature.length(); + String newSignature = fullName.substring(num + 1, fullName.length() - 1); + String[] arrayList = Strings.split(newSignature, ','); + Map map = new HashMap(); + List array = new ArrayList<>(); + for (String str : arrayList) { + String[] type = str.split(" "); + map.put(type[1], type[0]); + } + return new JSONObject(map); + } + + JSONObject getResult(String fullName, String eventSignature, Map topMap, Map dataMap) { + int num = eventSignature.length(); + String newSignature = fullName.substring(num + 1, fullName.length() - 1); + String[] arrayList = Strings.split(newSignature, ','); + Map map = new HashMap(); + List array = new ArrayList<>(); + int i = 0; + for (String str : arrayList) { + String[] type = str.split(" "); + + String ans; + String key = String.format("%d", i); + if (topMap.containsKey(key)) { + ans = topMap.get(key); + } else { + ans = dataMap.get(key); + } + + String tmp = ans; + if (type[0].equals("address")) { + ans = ByteArray.toHexString(decode58Check(ans)); + if (StringUtils.startsWith(ans, ADD_PRE_FIX_STRING_MAINNET)) { + ans = "0x" + ans.substring(2); + } else { + ans = tmp; + } + } + + i ++; + map.put(type[1], ans); + } + return new JSONObject(map); + } + + int getIndex(String unique) { + String[]id = unique.split("_"); + return Integer.parseInt(id[1]) - 1; + } + + private Runnable getSolidityBlockNumber = + () -> { + while (isRunRePushThread.get()) { + try { + QueryFactory query = new QueryFactory(); + query.setPageniate(QueryFactory.setPagniateVariable(0, 1, "-latestSolidifiedBlockNumber")); + List solidityTriggerEntityList + = mongoTemplate.find(query.getQuery(), + SolidityTriggerEntity.class); + if (solidityTriggerEntityList.isEmpty()) { + return; + } + latestSolidifiedBlockNumber.set(solidityTriggerEntityList.get(0).getLatestSolidifiedBlockNumber()); + TimeUnit.MILLISECONDS.sleep(1000L); + } catch (InterruptedException e) { + LOG.error(e.getMessage()); + } + } + }; + + @PostConstruct + public void init() { + Thread rePushThread = new Thread(getSolidityBlockNumber); + rePushThread.start(); + } + + int needConfirmed(String onlyConfirmed, String onlyUnconfirmed) { + if (onlyConfirmed.length() == 0 && onlyUnconfirmed.length() == 0) { + return RETURN_ALL_EVENTS; + } + if (onlyConfirmed.length() != 0 && onlyUnconfirmed.length() != 0) { + return CONFILICTING_PARAMETERS; + } + if (onlyConfirmed.length() != 0) { + return Boolean.parseBoolean(onlyConfirmed)? RETURN_ONLY_CONFIRMED_EVENTS : RETURN_ONLY_UNCONFIRMED_EVENTS; + } + if (onlyUnconfirmed.length() != 0) { + return Boolean.parseBoolean(onlyUnconfirmed)? RETURN_ONLY_UNCONFIRMED_EVENTS : RETURN_ONLY_CONFIRMED_EVENTS; + } + return RETURN_ALL_EVENTS; + } } diff --git a/src/main/java/org/tron/trongeventquery/contractevents/ContractEventTriggerEntity.java b/src/main/java/org/tron/trongeventquery/contractevents/ContractEventTriggerEntity.java index 260c1bd..1e50510 100644 --- a/src/main/java/org/tron/trongeventquery/contractevents/ContractEventTriggerEntity.java +++ b/src/main/java/org/tron/trongeventquery/contractevents/ContractEventTriggerEntity.java @@ -132,5 +132,4 @@ public ContractEventTriggerEntity(String eventSignature, Map top this.rawData = rawData; this.abiString = abiString; } - } diff --git a/src/main/java/org/tron/trongeventquery/contractlogs/ContractWithAbiController.java b/src/main/java/org/tron/trongeventquery/contractlogs/ContractWithAbiController.java index e759356..a573298 100644 --- a/src/main/java/org/tron/trongeventquery/contractlogs/ContractWithAbiController.java +++ b/src/main/java/org/tron/trongeventquery/contractlogs/ContractWithAbiController.java @@ -77,13 +77,14 @@ private JSONObject getContractTrigger(Map hmap, QueryFactory que ContractLogTriggerEntity.class); List contractEventTriggerList = mongoTemplate.find(query.getQuery(), ContractEventTriggerEntity.class); + Map map = new HashMap(); if (contractLogTriggerList.isEmpty() && contractEventTriggerList.isEmpty()) { - return null; + return new JSONObject(map); } if (!hmap.containsKey("abi") || hmap.get("abi").length() == 0) { - return null; + return new JSONObject(map); } String abi = hmap.get("abi"); @@ -96,7 +97,6 @@ private JSONObject getContractTrigger(Map hmap, QueryFactory que resLogList.addAll(QueryFactory.parseLogWithAbiByEvent(contractEventTriggerList, abi)); } - Map map = new HashMap(); if (resLogList != null && !resLogList.isEmpty()) { map.put("contractLogTriggers", resLogList); } diff --git a/src/main/java/org/tron/trongeventquery/filter/CommonFilter.java b/src/main/java/org/tron/trongeventquery/filter/CommonFilter.java new file mode 100644 index 0000000..8b02569 --- /dev/null +++ b/src/main/java/org/tron/trongeventquery/filter/CommonFilter.java @@ -0,0 +1,136 @@ +package org.tron.trongeventquery.filter; + + +import com.alibaba.fastjson.JSONObject; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; + +@WebFilter(urlPatterns = "/*") +public class CommonFilter implements Filter { + + + public static String TOTAL_REQUST = "TOTAL_REQUEST"; + public static String FAIL_REQUST = "FAIL_REQUEST"; + public static String FAIL4XX_REQUST = "FAIL4XX_REQUEST"; + public static String FAIL5XX_REQUST = "FAIL5XX_REQUEST"; + public static String OK_REQUST = "OK_REQUEST"; + private static int totalCount = 0; + private static int failCount = 0; + private static int count4xx=0; + private static int count5xx=0; + private static int okCount=0; + private static int interval = 1440; // 24 hour + private static HashMap EndpointCount = new HashMap(); + public String END_POINT = "END_POINT"; + public long gapMilliseconds = interval * 60 * 1000; + private long preciousTime = 0; + + public int getTotalCount() { + return this.totalCount; + } + + public int getInterval() { + return this.interval; + } + + public int getFailCount() { + return this.failCount; + } + + public int getOkCount() { return this.okCount; } + + public int getCount4xx() { + return count4xx; + } + public int getCount5xx() { + return count5xx; + } + + public HashMap getEndpointMap() { + return this.EndpointCount; + } + + public CommonFilter getInstance() { return this; } + + @Override public void init(FilterConfig filterConfig) throws ServletException { + // code here + preciousTime = System.currentTimeMillis(); + } + + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { +// System.out.println("--------------doFilter start--------------"); + long currentTime = System.currentTimeMillis(); + if (currentTime - preciousTime > gapMilliseconds) { //reset every 1 minutes + totalCount = 0; + failCount = 0; + count4xx=0; + count5xx=0; + okCount=0; + preciousTime = currentTime; + EndpointCount.clear(); + } + + if (request instanceof HttpServletRequest) { + String endpoint = ((HttpServletRequest) request).getRequestURI(); + JSONObject obj = new JSONObject(); + if (EndpointCount.containsKey(endpoint)) { + obj = EndpointCount.get(endpoint); + } else { + obj.put(TOTAL_REQUST, 0); + obj.put(FAIL_REQUST, 0); + obj.put(FAIL4XX_REQUST, 0); + obj.put(FAIL5XX_REQUST, 0); + obj.put(OK_REQUST, 0); + obj.put(END_POINT, endpoint); + } + obj.put(TOTAL_REQUST, (int) obj.get(TOTAL_REQUST) + 1); + totalCount++; + System.out.println("--response:"+response); + try { + chain.doFilter(request, response); + HttpServletResponse resp = (HttpServletResponse) response; +// System.out.println("--status:"+resp.getStatus()); +// System.out.println("--response:"+response); + if (resp.getStatus() != 200) { + failCount++; + count5xx=failCount-count4xx; + obj.put(FAIL_REQUST, (int) obj.get(FAIL_REQUST) + 1); + obj.put(FAIL5XX_REQUST, (int) obj.get(FAIL_REQUST)-(int) obj.get(FAIL4XX_REQUST)); + } + if (resp.getStatus() < 500 & resp.getStatus() > 399) { + count4xx++; + count5xx=failCount-count4xx; + obj.put(FAIL4XX_REQUST, (int) obj.get(FAIL4XX_REQUST) + 1); + obj.put(FAIL5XX_REQUST, (int) obj.get(FAIL_REQUST)-(int) obj.get(FAIL4XX_REQUST)); + } + } catch (Exception e) { + failCount++; + count5xx=failCount-count4xx; + obj.put(FAIL_REQUST, (int) obj.get(FAIL_REQUST) + 1); + obj.put(FAIL5XX_REQUST, (int) obj.get(FAIL_REQUST)-(int) obj.get(FAIL4XX_REQUST)); + throw e; + } + obj.put(OK_REQUST, (int) obj.get(TOTAL_REQUST) - (int) obj.get(FAIL_REQUST)); + okCount=totalCount-failCount; + // update map + EndpointCount.put(endpoint, obj); + } else { + chain.doFilter(request, response); + } +// System.out.println("TOTAL_REQUST:"+ totalCount); +// System.out.println("FAIL_REQUST:"+failCount); +// System.out.println("--------------doFilter stop--------------"); + } + + @Override + public void destroy() { + } +} \ No newline at end of file diff --git a/src/main/java/org/tron/trongeventquery/monitor/MonitorController.java b/src/main/java/org/tron/trongeventquery/monitor/MonitorController.java new file mode 100644 index 0000000..fceed54 --- /dev/null +++ b/src/main/java/org/tron/trongeventquery/monitor/MonitorController.java @@ -0,0 +1,28 @@ +package org.tron.trongeventquery.monitor; + + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +public class MonitorController { + + @Autowired + MonitorService monitorService; + + @RequestMapping(method = RequestMethod.GET, value = "/monitor") + public String getMonitor(){ + + MonitorInfo monitorInfo = monitorService.getMonitorInfo(); + String monitorInfoString = JSON.toJSONString(monitorInfo); +// Object parse = JSONObject.parse(monitorInfoString); + return monitorInfoString; + } +} diff --git a/src/main/java/org/tron/trongeventquery/monitor/MonitorInfo.java b/src/main/java/org/tron/trongeventquery/monitor/MonitorInfo.java new file mode 100644 index 0000000..7ae2a28 --- /dev/null +++ b/src/main/java/org/tron/trongeventquery/monitor/MonitorInfo.java @@ -0,0 +1,601 @@ +package org.tron.trongeventquery.monitor; + + +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class MonitorInfo { + private int status; + private String msg; + private DataInfo data; + + public int getStatus() { + return this.status; + } + + public MonitorInfo setStatus(int status) { + this.status = status; + return this; + } + + public String getMsg() { + return this.msg; + } + + public MonitorInfo setMsg(String msg) { + this.msg = msg; + return this; + } + + public DataInfo getDataInfo() { + return this.data; + } + + public MonitorInfo setDataInfo(DataInfo data) { + this.data = data; + return this; + } + +// public MonitorInfo ToProtoEntity() { +// Protocol.MonitorInfo.Builder builder = Protocol.MonitorInfo.newBuilder(); +// builder.setStatus(getStatus()); +// builder.setMsg(getMsg()); +// Protocol.MonitorInfo.DataInfo.Builder dataInfo = Protocol.MonitorInfo.DataInfo.newBuilder(); +// DataInfo data = getDataInfo(); +// dataInfo.setInterval(data.getInterval()); +// +// Protocol.MonitorInfo.DataInfo.NodeInfo.Builder nodeInfo = +// Protocol.MonitorInfo.DataInfo.NodeInfo.newBuilder(); +// DataInfo.NodeInfo node = data.getNodeInfo(); +// nodeInfo.setIp(node.getIp()); +// nodeInfo.setType(node.getType()); +// nodeInfo.setStatus(node.getType()); +// nodeInfo.setVersion(node.getVersion()); +// nodeInfo.setNoUpgradedSRCount(node.getNoUpgradedSRCount()); +// +// for (DataInfo.NodeInfo.NoUpgradedSR noUpgradedSR : node.getNoUpgradedSRList()) { +// Protocol.MonitorInfo.DataInfo.NodeInfo.NoUpgradedSR.Builder noUpgradeSRProto = +// Protocol.MonitorInfo.DataInfo.NodeInfo.NoUpgradedSR.newBuilder(); +// noUpgradeSRProto.setAddress(noUpgradedSR.getAddress()); +// noUpgradeSRProto.setUrl(noUpgradedSR.getUrl()); +// nodeInfo.addNoUpgradedSRList(noUpgradeSRProto.build()); +// } +// // set node info +// dataInfo.setNode(nodeInfo.build()); +// +// Protocol.MonitorInfo.DataInfo.BlockChainInfo.Builder blockChain = +// Protocol.MonitorInfo.DataInfo.BlockChainInfo.newBuilder(); +// DataInfo.BlochainInfo BlockChain = data.getBlockchainInfo(); +// blockChain.setHeadBlockTimestamp(BlockChain.getHeadBlockTimestamp()); +// blockChain.setHeadBlockHash(BlockChain.getHeadBlockHash()); +// blockChain.setBlockProcessTime(BlockChain.getBlockProcessTime()); +// blockChain.setForkCount(BlockChain.getForkCount()); +// blockChain.setHeadBlockNum(BlockChain.getHeadBlockNum()); +// blockChain.setTxCacheSize(BlockChain.getTxCacheSize()); +// blockChain.setMissedTxCount(BlockChain.getMissTxCount()); +// +// Protocol.MonitorInfo.DataInfo.BlockChainInfo.TPSInfo.Builder tpsInfo = +// Protocol.MonitorInfo.DataInfo.BlockChainInfo.TPSInfo.newBuilder(); +// DataInfo.BlochainInfo.TPSInfo TpsInfo = BlockChain.getTPS(); +// tpsInfo.setMeanRate(TpsInfo.getMeanRate()); +// tpsInfo.setOneMinuteRate(TpsInfo.getOneMinuteRate()); +// tpsInfo.setFiveMinuteRate(TpsInfo.getFiveMinuteRate()); +// tpsInfo.setFifteenMinuteRate(TpsInfo.getFifteenMinuteRate()); +// blockChain.setTPS(tpsInfo.build()); +// // set blockchain info +// dataInfo.setBlockchain(blockChain.build()); +// +// +// Protocol.MonitorInfo.DataInfo.NetInfo.Builder netInfo = +// Protocol.MonitorInfo.DataInfo.NetInfo.newBuilder(); +// DataInfo.NetInfo NetInfo = data.getNetInfo(); +// netInfo.setConnectionCount(NetInfo.getConnectionCount()); +// netInfo.setValidConnectionCount(NetInfo.getValidConnectionCount()); +// netInfo.setErrorProtoCount(NetInfo.getErrorProtoCount()); +// netInfo.setTCPInTraffic(NetInfo.getTCPInTraffic()); +// netInfo.setTCPOutTraffic(NetInfo.getTCPOutTraffic()); +// netInfo.setDisconnectionCount(NetInfo.getDisconnectionCount()); +// netInfo.setUDPInTraffic(NetInfo.getUDPInTraffic()); +// netInfo.setUDPOutTraffic(NetInfo.getUDPOutTraffic()); +// +// Protocol.MonitorInfo.DataInfo.NetInfo.ApiInfo.Builder apiInfo = +// Protocol.MonitorInfo.DataInfo.NetInfo.ApiInfo.newBuilder(); +// apiInfo.setTotalCount(NetInfo.getApi().getTotalCount()); +// apiInfo.setTotalFailCount(NetInfo.getApi().getTotalFailCount()); +// for (DataInfo.NetInfo.ApiInfo.ApiDetailInfo ApiDetail : NetInfo.getApi().getApiDetailInfo()) { +// Protocol.MonitorInfo.DataInfo.NetInfo.ApiInfo.ApiDetailInfo.Builder apiDetail = +// Protocol.MonitorInfo.DataInfo.NetInfo.ApiInfo.ApiDetailInfo.newBuilder(); +// apiDetail.setName(ApiDetail.getName()); +// apiDetail.setCount(ApiDetail.getCount()); +// apiDetail.setFailCount(ApiDetail.getFailCount()); +// apiInfo.addDetail(apiDetail.build()); +// } +// netInfo.setApi(apiInfo.build()); +// +// +// for (DataInfo.NetInfo.DisconnectionDetailInfo DisconnectionDetail : NetInfo +// .getDisconnectionDetail()) { +// Protocol.MonitorInfo.DataInfo.NetInfo.DisconnectionDetailInfo.Builder disconnectionDetail = +// Protocol.MonitorInfo.DataInfo.NetInfo.DisconnectionDetailInfo.newBuilder(); +// disconnectionDetail.setReason(DisconnectionDetail.getReason()); +// disconnectionDetail.setCount(DisconnectionDetail.getCount()); +// netInfo.addDisconnectionDetail(disconnectionDetail.build()); +// } +// +// Protocol.MonitorInfo.DataInfo.NetInfo.LatencyInfo.Builder latencyInfo = +// Protocol.MonitorInfo.DataInfo.NetInfo.LatencyInfo.newBuilder(); +// latencyInfo.setDelay1S(NetInfo.getLatency().getDelay1S()); +// latencyInfo.setDelay2S(NetInfo.getLatency().getDelay2S()); +// latencyInfo.setDelay3S(NetInfo.getLatency().getDelay3S()); +// latencyInfo.setTop99(NetInfo.getLatency().getTop99()); +// latencyInfo.setTop95(NetInfo.getLatency().getTop95()); +// latencyInfo.setTotalCount(NetInfo.getLatency().getTotalCount()); +// +// for (DataInfo.NetInfo.LatencyInfo.LatencyDetailInfo LatencyDetailInfo : NetInfo.getLatency() +// .getLatencyDetailInfo()) { +// Protocol.MonitorInfo.DataInfo.NetInfo.LatencyInfo.LatencyDetailInfo.Builder latencyDetail = +// Protocol.MonitorInfo.DataInfo.NetInfo.LatencyInfo.LatencyDetailInfo.newBuilder(); +// latencyDetail.setCount(LatencyDetailInfo.getCount()); +// latencyDetail.setWitness(LatencyDetailInfo.getWitness()); +// latencyDetail.setTop99(LatencyDetailInfo.getTop99()); +// latencyDetail.setTop95(LatencyDetailInfo.getTop95()); +// latencyDetail.setDelay1S(LatencyDetailInfo.getDelay1S()); +// latencyDetail.setDelay2S(LatencyDetailInfo.getDelay2S()); +// latencyDetail.setDelay3S(LatencyDetailInfo.getDelay3S()); +// latencyInfo.addDetail(latencyDetail.build()); +// } +// +// // set latency info +// netInfo.setLatency(latencyInfo.build()); +// // set net info +// dataInfo.setNet(netInfo.build()); +// // set data info +// builder.setData(dataInfo.build()); +// return builder.build(); +// } + + + public static class DataInfo { + private int interval; + private NetInfo net; + + public int getInterval() { + return this.interval; + } + + public DataInfo setInterval(int interval) { + this.interval = interval; + return this; + } + + public NetInfo getNetInfo() { + return this.net; + } + + public DataInfo setNetInfo(NetInfo net) { + this.net = net; + return this; + } + + // network monitor information + public static class NetInfo { + private int errorProtoCount; + private ApiInfo api; + private int connectionCount; + private int validConnectionCount; + private long TCPInTraffic; + private long TCPOutTraffic; + private int disconnectionCount; + private List disconnectionDetail = new ArrayList<>(); + private long UDPInTraffic; + private long UDPOutTraffic; + private LatencyInfo latency; + + public int getErrorProtoCount() { + return this.errorProtoCount; + } + + public NetInfo setErrorProtoCount(int errorProtoCount) { + this.errorProtoCount = errorProtoCount; + return this; + } + + public ApiInfo getApi() { + return this.api; + } + + public NetInfo setApi(ApiInfo api) { + this.api = api; + return this; + } + + public int getConnectionCount() { + return this.connectionCount; + } + + public NetInfo setConnectionCount(int connectionCount) { + this.connectionCount = connectionCount; + return this; + } + + public int getValidConnectionCount() { + return this.validConnectionCount; + } + + public NetInfo setValidConnectionCount(int validConnectionCount) { + this.validConnectionCount = validConnectionCount; + return this; + } + + public long getTCPInTraffic() { + return this.TCPInTraffic; + } + + public NetInfo setTCPInTraffic(long TCPInTraffic) { + this.TCPInTraffic = TCPInTraffic; + return this; + } + + public long getTCPOutTraffic() { + return this.TCPOutTraffic; + } + + public NetInfo setTCPOutTraffic(long TCPOutTraffic) { + this.TCPOutTraffic = TCPOutTraffic; + return this; + } + + public int getDisconnectionCount() { + return this.disconnectionCount; + } + + public NetInfo setDisconnectionCount(int disconnectionCount) { + this.disconnectionCount = disconnectionCount; + return this; + } + + public List getDisconnectionDetail() { + return this.disconnectionDetail; + } + + public NetInfo setDisconnectionDetail(List disconnectionDetail) { + this.disconnectionDetail = disconnectionDetail; + return this; + } + + public long getUDPInTraffic() { + return this.UDPInTraffic; + } + + public NetInfo setUDPInTraffic(long UDPInTraffic) { + this.UDPInTraffic = UDPInTraffic; + return this; + } + + public long getUDPOutTraffic() { + return this.UDPOutTraffic; + } + + public NetInfo setUDPOutTraffic(long UDPOutTraffic) { + this.UDPOutTraffic = UDPOutTraffic; + return this; + } + + public LatencyInfo getLatency() { + return this.latency; + } + + public NetInfo setLatency(LatencyInfo latency) { + this.latency = latency; + return this; + } + + // API monitor information + public static class ApiInfo { + private int totalCount; + private int totalFailCount; + private int totalCount2xx; + private int totalCount4xx; + private int totalCount5xx; + + private List detail = new ArrayList<>(); + + public int getTotalCount() { + return this.totalCount; + } + + public ApiInfo setTotalCount(int totalCount) { + this.totalCount = totalCount; + return this; + } + + public int getTotalFailCount() { + return this.totalFailCount; + } + + public ApiInfo setTotalFailCount(int totalFailCount) { + this.totalFailCount = totalFailCount; + return this; + } + + public int getTotalCount2xx() { + return this.totalCount2xx; + } + + public ApiInfo setTotalCount2xx(int totalCount2xx) { + this.totalCount2xx = totalCount2xx; + return this; + } + + public int getTotalCount4xx() { + return this.totalCount4xx; + } + + public ApiInfo setTotalCount4xx(int totalCount4xx) { + this.totalCount4xx = totalCount4xx; + return this; + } + + public int getTotalCount5xx() { + return this.totalCount5xx; + } + + public ApiInfo setTotalCount5xx(int totalCount5xx) { + this.totalCount5xx = totalCount5xx; + return this; + } + + public List getApiDetailInfo() { + return this.detail; + } + + public ApiInfo setApiDetailInfo(List detail) { + this.detail = detail; + return this; + } + + public static class ApiDetailInfo { + private String name; + private int count; + private int failCount; + private int count4xx; + private int count5xx; + private int count2xx; + + + public String getName() { + return this.name; + } + + public ApiDetailInfo setName(String name) { + this.name = name; + return this; + } + + public int getCount() { + return this.count; + } + + public ApiDetailInfo setCount(int count) { + this.count = count; + return this; + } + + public int getFailCount() { + return this.failCount; + } + + public ApiDetailInfo setFailCount(int failCount) { + this.failCount = failCount; + return this; + } + + public int getCount4xx() { + return this.count4xx; + } + + public ApiDetailInfo setCount4xx(int count4xx) { + this.count4xx = count4xx; + return this; + } + + public int getCount5xx() { + return this.count5xx; + } + + public ApiDetailInfo setCount5xx(int count5xx) { + this.count5xx = count5xx; + return this; + } + public int getCount2xx() { + return this.count2xx; + } + + public ApiDetailInfo setCount2xx(int count2xx) { + this.count2xx = count2xx; + return this; + } + } + } + + // disconnection monitor information + public static class DisconnectionDetailInfo { + private String reason; + private int count; + + public String getReason() { + return this.reason; + } + + public DisconnectionDetailInfo setReason(String reason) { + this.reason = reason; + return this; + } + + public int getCount() { + return this.count; + } + + public DisconnectionDetailInfo setCount(int count) { + this.count = count; + return this; + } + + } + + // latency monitor information + public static class LatencyInfo { + private int top99; + private int top95; + private int totalCount; + private int delay1S; + private int delay2S; + private int delay3S; + private List detail = new ArrayList<>(); + + public int getTop99() { + return this.top99; + } + + public LatencyInfo setTop99(int top99) { + this.top99 = top99; + return this; + } + + public int getTop95() { + return this.top95; + } + + public LatencyInfo setTop95(int top95) { + this.top95 = top95; + return this; + } + + public int getTotalCount() { + return this.totalCount; + } + + public LatencyInfo setTotalCount(int totalCount) { + this.totalCount = totalCount; + return this; + } + + public int getDelay1S() { + return this.delay1S; + } + + public LatencyInfo setDelay1S(int delay1S) { + this.delay1S = delay1S; + return this; + } + + public int getDelay2S() { + return this.delay2S; + } + + public LatencyInfo setDelay2S(int delay2S) { + this.delay2S = delay2S; + return this; + } + + public int getDelay3S() { + return this.delay3S; + } + + public LatencyInfo setDelay3S(int delay3S) { + this.delay3S = delay3S; + return this; + } + + public List getLatencyDetailInfo() { + return this.detail; + } + + public LatencyInfo setLatencyDetailInfo(List detail) { + this.detail = detail; + return this; + } + + public static class LatencyDetailInfo { + private String witness; + private int top99; + private int top95; + private int count; + private int delay1S; + private int delay2S; + private int delay3S; + + public String getWitness() { + return this.witness; + } + + public LatencyDetailInfo setWitness(String witness) { + this.witness = witness; + return this; + } + + public int getTop99() { + return this.top99; + } + + public LatencyDetailInfo setTop99(int top99) { + this.top99 = top99; + return this; + } + + public int getTop95() { + return this.top95; + } + + public LatencyDetailInfo setTop95(int top95) { + this.top95 = top95; + return this; + } + + public int getCount() { + return this.count; + } + + public LatencyDetailInfo setCount(int count) { + this.count = count; + return this; + } + + public int getDelay1S() { + return this.delay1S; + } + + public LatencyDetailInfo setDelay1S(int delay1S) { + this.delay1S = delay1S; + return this; + } + + public int getDelay2S() { + return this.delay2S; + } + + public LatencyDetailInfo setDelay2S(int delay2S) { + this.delay2S = delay2S; + return this; + } + + public int getDelay3S() { + return this.delay3S; + } + + public LatencyDetailInfo setDelay3S(int delay3S) { + this.delay3S = delay3S; + return this; + } + + } + } + + } + + + } +} diff --git a/src/main/java/org/tron/trongeventquery/monitor/MonitorService.java b/src/main/java/org/tron/trongeventquery/monitor/MonitorService.java new file mode 100644 index 0000000..ec8929e --- /dev/null +++ b/src/main/java/org/tron/trongeventquery/monitor/MonitorService.java @@ -0,0 +1,63 @@ +package org.tron.trongeventquery.monitor; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.trongeventquery.filter.CommonFilter; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Slf4j(topic = "monitorService") +@Component +public class MonitorService { + +// @Autowired +// private MonitorMetric monitorMetric; + + public MonitorInfo getMonitorInfo() { + MonitorInfo monitorInfo = new MonitorInfo(); + monitorInfo.setStatus(1); + monitorInfo.setMsg("success"); + MonitorInfo.DataInfo data = new MonitorInfo.DataInfo(); + setNetInfo(data); + monitorInfo.setDataInfo(data); + +// return monitorInfo.ToProtoEntity(); + return monitorInfo; + } + + public void setNetInfo(MonitorInfo.DataInfo data) { + MonitorInfo.DataInfo.NetInfo netInfo = new MonitorInfo.DataInfo.NetInfo(); + + // set api request info + MonitorInfo.DataInfo.NetInfo.ApiInfo apiInfo = new MonitorInfo.DataInfo.NetInfo.ApiInfo(); + CommonFilter commonFilter=new CommonFilter(); + apiInfo.setTotalCount(commonFilter.getInstance().getTotalCount()); + apiInfo.setTotalCount2xx(commonFilter.getInstance().getOkCount()); + apiInfo.setTotalFailCount(commonFilter.getInstance().getFailCount()); + apiInfo.setTotalCount4xx(commonFilter.getInstance().getCount4xx()); + apiInfo.setTotalCount5xx(commonFilter.getInstance().getCount5xx()); + List apiDetails = new ArrayList<>(); + for(Map.Entry entry: commonFilter.getInstance().getEndpointMap().entrySet()){ + MonitorInfo.DataInfo.NetInfo.ApiInfo.ApiDetailInfo apiDetail = + new MonitorInfo.DataInfo.NetInfo.ApiInfo.ApiDetailInfo(); + apiDetail.setName(entry.getKey()); + apiDetail.setCount((int)entry.getValue().get(CommonFilter.TOTAL_REQUST)); + apiDetail.setFailCount((int)entry.getValue().get(CommonFilter.FAIL_REQUST)); + apiDetail.setCount2xx((int)entry.getValue().get(CommonFilter.OK_REQUST)); + apiDetail.setCount4xx((int)entry.getValue().get(CommonFilter.FAIL4XX_REQUST)); + apiDetail.setCount5xx((int)entry.getValue().get(CommonFilter.FAIL5XX_REQUST)); + apiDetails.add(apiDetail); + } + apiInfo.setApiDetailInfo(apiDetails); + netInfo.setApi(apiInfo); + + data.setNetInfo(netInfo); + + } + +} diff --git a/src/main/java/org/tron/trongeventquery/query/ContractEventParser.java b/src/main/java/org/tron/trongeventquery/query/ContractEventParser.java index 8c4df37..d005ebe 100644 --- a/src/main/java/org/tron/trongeventquery/query/ContractEventParser.java +++ b/src/main/java/org/tron/trongeventquery/query/ContractEventParser.java @@ -1,5 +1,8 @@ package org.tron.trongeventquery.query; + +import static org.tron.common.utils.LogConfig.LOG; + import java.math.BigInteger; import java.util.regex.Pattern; import lombok.extern.slf4j.Slf4j; @@ -12,7 +15,7 @@ import org.tron.common.runtime.vm.DataWord; import org.tron.core.Wallet; -@Slf4j(topic = "Parser") + public class ContractEventParser { private static final int DATAWORD_UNIT_SIZE = 32; @@ -52,7 +55,7 @@ protected static String parseDataBytes(byte[] data, String typeStr, int index) { return type == Type.STRING ? new String(realBytes) : Hex.toHexString(realBytes); } } catch (OutputLengthException | ArithmeticException e) { - log.debug("parseDataBytes ", e); + LOG.debug("parseDataBytes ", e); } throw new UnsupportedOperationException("unsupported type:" + typeStr); } diff --git a/src/main/java/org/tron/trongeventquery/query/ContractEventParserJson.java b/src/main/java/org/tron/trongeventquery/query/ContractEventParserJson.java index 7f026bd..9030325 100644 --- a/src/main/java/org/tron/trongeventquery/query/ContractEventParserJson.java +++ b/src/main/java/org/tron/trongeventquery/query/ContractEventParserJson.java @@ -1,6 +1,8 @@ package org.tron.trongeventquery.query; +import static org.tron.common.utils.LogConfig.LOG; + import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import java.util.HashMap; @@ -11,7 +13,6 @@ import org.pf4j.util.StringUtils; import org.spongycastle.util.encoders.Hex; -@Slf4j(topic = "Parser") public class ContractEventParserJson extends ContractEventParser { /** @@ -30,20 +31,22 @@ public static Map parseTopics(List topicList, JSONObject // in case indexed topics doesn't match if (topicsMatched(topicList, entry)) { - for (int i = 0; i < inputs.size(); ++i) { - JSONObject param = inputs.getJSONObject(i); - Boolean indexed = param.getBoolean("indexed"); - if (indexed == null || !indexed) { - continue; - } - if (index >= topicList.size()) { - break; - } - String str = parseTopic(topicList.get(index++), param.getString("type")); - if (StringUtils.isNotNullOrEmpty(param.getString("name"))) { - map.put(param.getString("name"), str); + if (inputs != null) { + for (int i = 0; i < inputs.size(); ++i) { + JSONObject param = inputs.getJSONObject(i); + Boolean indexed = param.getBoolean("indexed"); + if (indexed == null || !indexed) { + continue; + } + if (index >= topicList.size()) { + break; + } + String str = parseTopic(topicList.get(index++), param.getString("type")); + if (StringUtils.isNotNullOrEmpty(param.getString("name"))) { + map.put(param.getString("name"), str); + } + map.put("" + i, str); } - map.put("" + i, str); } } else { for (int i = 1; i < topicList.size(); ++i) { @@ -100,7 +103,7 @@ public static Map parseEventData(byte[] data, map.put("0", Hex.toHexString(data)); } } catch (UnsupportedOperationException e) { - log.debug("UnsupportedOperationException", e); + LOG.debug("UnsupportedOperationException", e); map.clear(); map.put(startIndex.toString(), Hex.toHexString(data)); } @@ -113,11 +116,13 @@ private static boolean topicsMatched(List topicList, JSONObject entry) { } int inputSize = 1; JSONArray inputs = entry.getJSONArray("inputs"); - for (int i = 0; i < inputs.size(); i++) { - JSONObject param = inputs.getJSONObject(i); - Boolean indexed = param.getBoolean("indexed"); - if (indexed != null && indexed) { - inputSize++; + if (inputs != null) { + for (int i = 0; i < inputs.size(); i++) { + JSONObject param = inputs.getJSONObject(i); + Boolean indexed = param.getBoolean("indexed"); + if (indexed != null && indexed) { + inputSize++; + } } } return inputSize == topicList.size(); diff --git a/src/main/java/org/tron/trongeventquery/query/QueryFactory.java b/src/main/java/org/tron/trongeventquery/query/QueryFactory.java index 2a69846..43d8945 100644 --- a/src/main/java/org/tron/trongeventquery/query/QueryFactory.java +++ b/src/main/java/org/tron/trongeventquery/query/QueryFactory.java @@ -122,7 +122,11 @@ public void setBlockNumGte(long block) { this.query.addCriteria(Criteria.where("blockNumber").gte(block)); } - public void setBlockNumSmall(long block) { + public void setBlockNumGt(long block) { + this.query.addCriteria(Criteria.where("blockNumber").gt(block)); + } + + public void setBlockNumLte(long block) { this.query.addCriteria(Criteria.where("blockNumber").lte(block)); } diff --git a/src/main/java/org/tron/trongeventquery/response/Response.java b/src/main/java/org/tron/trongeventquery/response/Response.java new file mode 100644 index 0000000..d32f146 --- /dev/null +++ b/src/main/java/org/tron/trongeventquery/response/Response.java @@ -0,0 +1,19 @@ +package org.tron.trongeventquery.response; + +import com.alibaba.fastjson.JSONObject; + + +public class Response { + public Response(boolean result, String msg) { + jsonObject = new JSONObject(); + jsonObject.put("success", result); + jsonObject.put("error", msg); + } + + public JSONObject toJSONObject() { + return jsonObject; + } + + private JSONObject jsonObject; + +} \ No newline at end of file diff --git a/src/main/java/org/tron/trongeventquery/solidityevents/SolidityTriggerEntity.java b/src/main/java/org/tron/trongeventquery/solidityevents/SolidityTriggerEntity.java new file mode 100644 index 0000000..d64e58a --- /dev/null +++ b/src/main/java/org/tron/trongeventquery/solidityevents/SolidityTriggerEntity.java @@ -0,0 +1,42 @@ +package org.tron.trongeventquery.solidityevents; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +@Document(collection = "solidity") +public class SolidityTriggerEntity implements Serializable { + + private static final long serialVersionUID = -70777625567836430L; + + @Id + private String id; + + @Field(value = "latestSolidifiedBlockNumber") + @JsonProperty(value = "latestSolidifiedBlockNumber") + private long latestSolidifiedBlockNumber; + + @Field(value = "timeStamp") + @JsonProperty(value = "timeStamp") + private long timeStamp; + + @Field(value = "triggerName") + @JsonProperty(value = "triggerName") + private String triggerName; + + public long getLatestSolidifiedBlockNumber() { + return latestSolidifiedBlockNumber; + } + + public SolidityTriggerEntity(Long timeStamp, + String triggerName, long latestSolidifiedBlockNumber) { + this.timeStamp = timeStamp; + this.triggerName = triggerName; + this.latestSolidifiedBlockNumber = latestSolidifiedBlockNumber; + } +} diff --git a/src/main/java/org/tron/trongeventquery/transactions/TransactionTriggerEntity.java b/src/main/java/org/tron/trongeventquery/transactions/TransactionTriggerEntity.java index 765c953..56b8182 100644 --- a/src/main/java/org/tron/trongeventquery/transactions/TransactionTriggerEntity.java +++ b/src/main/java/org/tron/trongeventquery/transactions/TransactionTriggerEntity.java @@ -107,6 +107,10 @@ public class TransactionTriggerEntity implements Serializable { @JsonProperty(value = "latestSolidifiedBlockNumber") private long latestSolidifiedBlockNumber; + @Field(value = "data") + @JsonProperty(value = "data") + private String data; + public String getContractType() { return contractType; } @@ -118,7 +122,7 @@ public TransactionTriggerEntity(String transactionId, String blockHash, String fromAddress, String toAddress, String assetName, long assetAmount, String contractResult,long contractCallValue, String result, String contractAddress, String contractType, - long feeLimit,long timeStamp, long latestSolidifiedBlockNumber) { + long feeLimit,long timeStamp, long latestSolidifiedBlockNumber, String data) { this.transactionId = transactionId; this.blockHash = blockHash; this.blockNumber = blockNumber; @@ -141,5 +145,6 @@ public TransactionTriggerEntity(String transactionId, String blockHash, this.feeLimit = feeLimit; this.timeStamp = timeStamp; this.latestSolidifiedBlockNumber = latestSolidifiedBlockNumber; + this.data = data; } } \ No newline at end of file