1、增加get接口:获取目前系统接收到的交易总数;

2、增加post接口:1)通过高度2)通过txid获取所在块的时间戳(交易入块时间);
3、修改查询交易入块时间的接口,增加utc时间(13位的ms级)
This commit is contained in:
brightestboy 2019-09-16 09:41:02 +08:00
parent 0af717c136
commit 9b2dc19031
4 changed files with 109 additions and 38 deletions

View File

@ -42,6 +42,7 @@ import akka.actor.Props
import rep.crypto.cert.SignTool
import rep.protos.peer.ActionResult
import rep.app.conf.SystemProfile
import rep.log.RepLogger
import rep.network.base.ModuleBase
import rep.sc.TypeOfSender
import rep.sc.SandboxDispatcher.DoTransaction
@ -60,12 +61,14 @@ object RestActor {
case object ChainInfo
case object NodeNumber
case object TransNumber
case object AcceptedTransNumber
case class SystemStart(cout: Int)
case class SystemStop(from: Int, to: Int)
case class BlockId(bid: String)
case class BlockHeight(h: Int)
case class BlockTime(createTime: String, createTimeUtc: String)
case class BlockTimeForHeight(h:Long)
case class BlockTimeForTxid(txid:String)
case class BlockHeightStream(h: Int)
@ -159,6 +162,7 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
sender ! PostResult(t.id, None, Option(s"transactionId is exists, the transaction is \n ${JsonFormat.toJson(st.get)}"))
case None =>
if (SignTool.verify(sig, tOutSig.toByteArray, certId, pe.getSysTag)) {
// RepLogger.info(RepLogger.Business_Logger, s"验证签名成功txid: ${t.id},creditCode: ${t.signature.get.getCertId.creditCode}, certName: ${t.signature.get.getCertId.certName}")
val future = pe.getActorRef(ActorType.transactiondispatcher) ? DoTransaction(t, "api_" + t.id, TypeOfSender.FromAPI)
val result = Await.result(future, timeout.duration).asInstanceOf[DoTransactionResult]
val rv = result
@ -248,7 +252,7 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
val r = bb match {
case null => QueryResult(None)
case _ =>
QueryResult(Option(JsonMethods.parse(string2JsonInput("{"+"\"createtime\":\""+bb+"\"}"))))
QueryResult(Option(JsonMethods.parse(bb)))
}
sender ! r
@ -257,7 +261,7 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
val r = bb match {
case null => QueryResult(None)
case _ =>
QueryResult(Option(JsonMethods.parse(string2JsonInput("{"+"\"createtime\":\""+bb+"\"}"))))
QueryResult(Option(JsonMethods.parse(bb)))
}
sender ! r
@ -318,11 +322,14 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
val rs = "{\"consensusnodes\":\""+stablenode+"\",\"nodes\":\""+snode+"\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
case TransNumber =>
case TransNumber =>
val num = pe.getTransPoolMgr.getTransLength()
val rs = "{\"numberofcache\":\""+num+"\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
case AcceptedTransNumber =>
val num = sr.getBlockChainInfo.height + pe.getTransPoolMgr.getTransLength()
val rs = "{\"acceptedNumber\":\""+num+"\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
}
}

View File

@ -16,8 +16,8 @@
package rep.api.rest
import scala.concurrent.{ ExecutionContext, Future }
import akka.actor.{ ActorRef, ActorSelection }
import scala.concurrent.{ExecutionContext, Future}
import akka.actor.{ActorRef, ActorSelection}
import akka.util.Timeout
import akka.http.scaladsl.model.Uri.Path.Segment
import akka.http.scaladsl.server.Directives
@ -30,29 +30,26 @@ import Directives._
import rep.sc.Sandbox.SandboxException
import rep.sc.Sandbox._
import rep.sc.Shim._
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import rep.protos.peer._
import rep.api.rest.RestActor._
import spray.json.DefaultJsonProtocol._
import org.json4s.{ DefaultFormats, Formats, jackson }
import org.json4s.{DefaultFormats, Formats, jackson}
import akka.http.scaladsl.server.Directives
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport
import akka.http.scaladsl.model.{ ContentTypes, HttpCharsets, MediaTypes }
import akka.http.scaladsl.unmarshalling.{ FromEntityUnmarshaller, Unmarshaller }
import akka.http.scaladsl.model.{ContentTypes, HttpCharsets, MediaTypes}
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import scala.xml.NodeSeq
import rep.log.RepLogger
/**
* 获得区块链的概要信息
* @author c4w
*/
* 获得区块链的概要信息
*
* @author c4w
*/
@Api(value = "/chaininfo", description = "获得当前区块链信息", produces = "application/json")
@Path("chaininfo")
class ChainService(ra: ActorRef)(implicit executionContext: ExecutionContext)
@ -62,11 +59,12 @@ class ChainService(ra: ActorRef)(implicit executionContext: ExecutionContext)
import scala.concurrent.duration._
import Json4sSupport._
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
implicit val timeout = Timeout(20.seconds)
val route = getBlockChainInfo ~ getNodeNumber ~ getCacheTransNumber
val route = getBlockChainInfo ~ getNodeNumber ~ getCacheTransNumber ~ getAcceptedTransNumber
@ApiOperation(value = "返回块链信息", notes = "", nickname = "getChainInfo", httpMethod = "GET")
@ApiResponses(Array(
@ -94,7 +92,7 @@ class ChainService(ra: ActorRef)(implicit executionContext: ExecutionContext)
}
}
}
@Path("/getcachetransnumber")
@ApiOperation(value = "返回系统缓存交易数量", notes = "", nickname = "getCacheTransNumber", httpMethod = "GET")
@ApiResponses(Array(
@ -108,26 +106,46 @@ class ChainService(ra: ActorRef)(implicit executionContext: ExecutionContext)
}
}
}
@Path("/getAcceptedTransNumber")
@ApiOperation(value = "返回系统接收到的交易数量", notes = "", nickname = "getAcceptedTransNumber", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回系统接收到的交易数量", response = classOf[QueryResult])))
def getAcceptedTransNumber =
path("chaininfo" / "getAcceptedTransNumber") {
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get number of accepted")
complete {
(ra ? AcceptedTransNumber).mapTo[QueryResult]
}
}
}
}
}
/**
* 获得指定区块的详细信息
* @author c4w
*/
* 获得指定区块的详细信息
*
* @author c4w
*/
@Api(value = "/block", description = "获得区块数据", produces = "application/json")
@Path("block")
class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
extends Directives {
import akka.pattern.ask
import scala.concurrent.duration._
implicit val timeout = Timeout(20.seconds)
import Json4sSupport._
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
val route = getBlockById ~ getBlockByHeight ~ getBlockStreamByHeight ~ getBlockTimeOfCreate ~ getBlockTimeOfTransaction
val route = getBlockById ~ getBlockByHeight ~ getBlockByHeightToo ~ getBlockStreamByHeight ~ getBlockTimeOfCreate ~ getBlockTimeOfTxrByTxid ~ getBlockTimeOfTransaction
@Path("/hash/{blockId}")
@ApiOperation(value = "返回指定id的区块", notes = "", nickname = "getBlockById", httpMethod = "GET")
@ -151,7 +169,7 @@ class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
new ApiImplicitParam(name = "blockHeight", value = "区块高度", required = true, dataType = "int", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回区块json内容", response = classOf[QueryResult])))
def getBlockByHeight =
def getBlockByHeightToo =
path("block" / Segment) { blockHeight =>
get {
extractClientIP { ip =>
@ -163,6 +181,25 @@ class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
}
}
@Path("/blockHeight")
@ApiOperation(value = "返回指定高度的区块", notes = "", nickname = "getBlockByHeight", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "height", value = "区块高度", required = true, dataType = "String", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回区块json内容", response = classOf[QueryResult])))
def getBlockByHeight =
path("block" / "blockHeight") {
post {
entity(as[Map[String, Int]]) { blockQuery =>
complete {
(ra ? BlockHeight(blockQuery("height"))).mapTo[QueryResult]
}
}
}
}
@Path("/blocktime/{blockHeight}")
@ApiOperation(value = "返回指定高度的区块的出块时间", notes = "", nickname = "getBlockTimeOfCreate", httpMethod = "GET")
@ApiImplicitParams(Array(
@ -170,7 +207,7 @@ class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回指定高度的区块的出块时间", response = classOf[QueryResult])))
def getBlockTimeOfCreate =
path("block" /"blocktime"/ Segment) { blockHeight =>
path("block" / "blocktime" / Segment) { blockHeight =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get block time for Height,block height=${blockHeight}")
@ -180,7 +217,7 @@ class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
//complete { (ra ? BlockHeight(blockHeight.toInt)).mapTo[QueryResult] }
}
}
@Path("/blocktimeoftran/{transid}")
@ApiOperation(value = "返回指定交易的入块时间", notes = "", nickname = "getBlockTimeOfTransaction", httpMethod = "GET")
@ApiImplicitParams(Array(
@ -198,7 +235,23 @@ class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
//complete { (ra ? BlockHeight(blockHeight.toInt)).mapTo[QueryResult] }
}
}
@Path("/blocktimeoftran")
@ApiOperation(value = "返回指定交易的入块时间", notes = "", nickname = "getBlockTimeOfTransaction", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "txid", value = "交易id", required = true, dataType = "String", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回指定交易的入块时间", response = classOf[QueryResult])))
def getBlockTimeOfTxrByTxid=
path("block" / "blocktimeoftran") {
post {
entity(as[Map[String, String]]) { trans =>
complete { (ra ? BlockTimeForTxid(trans("txid"))).mapTo[QueryResult] }
}
}
}
@Path("/stream/{blockHeight}")
@ApiOperation(value = "返回指定高度的区块字节流", notes = "", nickname = "getBlockStreamByHeight", httpMethod = "GET")
@ApiImplicitParams(Array(
@ -217,9 +270,10 @@ class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
}
/**
* 获得指定交易的详细信息提交签名交易
* @author c4w
*/
* 获得指定交易的详细信息提交签名交易
*
* @author c4w
*/
@Api(value = "/transaction", description = "获得交易数据", consumes = "application/json,application/xml", produces = "application/json,application/xml")
@Path("transaction")
class TransactionService(ra: ActorRef)(implicit executionContext: ExecutionContext)
@ -230,11 +284,12 @@ class TransactionService(ra: ActorRef)(implicit executionContext: ExecutionConte
import java.io.FileInputStream
implicit val timeout = Timeout(20.seconds)
import Json4sSupport._
import ScalaXmlSupport._
import akka.stream.scaladsl.FileIO
import akka.util.ByteString
import java.nio.file.{ Paths, Files }
import java.nio.file.{Paths, Files}
import akka.stream.scaladsl.Framing
implicit val serialization = jackson.Serialization // or native.Serialization
@ -279,7 +334,7 @@ class TransactionService(ra: ActorRef)(implicit executionContext: ExecutionConte
}
}
}
@Path("/stream/{transactionId}")
@ApiOperation(value = "返回指定id的交易字节流", notes = "", nickname = "getTransactionStream", httpMethod = "GET", produces = "application/octet-stream")

View File

@ -67,7 +67,8 @@ object RepChain_Multi {
var nodes = Set.empty[ClusterSystem]
nodes += sys1
for (i <- 1 to 9) {
// 可以根据自己的需要将nodelist.length改成对应的节点数
for (i <- 1 to nodelist.length) {
Thread.sleep(2000)
val sysN = new ClusterSystem(nodelist(i), InitType.MULTI_INIT, true)
sysN.init

View File

@ -20,6 +20,7 @@ import rep.storage.block._
import rep.storage.leveldb._
import rep.storage.cfg._
import rep.protos.peer._
import scala.collection.JavaConverters._
import com.google.protobuf.ByteString
import com.fasterxml.jackson.core.Base64Variants
@ -29,7 +30,10 @@ import org.json4s.jackson.JsonMethods
import rep.sc.Shim._
import rep.utils._
import java.io._
import rep.api.rest.RestActor.BlockTime
import rep.protos.peer.OperLog
import scala.collection.mutable._
import rep.network.consensus.util.BlockHelp
import rep.log.RepLogger
@ -38,6 +42,7 @@ import rep.storage.util.pathUtil
import rep.log.RepTimeTracer
import rep.app.conf.SystemProfile
import rep.crypto.cert.certCache
import scala.util.control.Breaks._
/**
@ -393,7 +398,7 @@ class ImpDataAccess private (SystemName: String) extends IDataAccess(SystemName)
* @return 返回出块时间
*/
override def getBlockTimeOfTxid(txid: String): String = {
this.getBlockTime4Block(this.getBlock4ObjectByTxId(txid))
SerializeUtils.toJson(this.getBlockTime4Block(this.getBlock4ObjectByTxId(txid)))
}
/**
@ -405,18 +410,21 @@ class ImpDataAccess private (SystemName: String) extends IDataAccess(SystemName)
* @return 返回出块时间
*/
def getBlockTimeOfHeight(h: Long): String = {
this.getBlockTime4Block(this.getBlock4ObjectByHeight(h))
SerializeUtils.toJson(this.getBlockTime4Block(this.getBlock4ObjectByHeight(h)))
}
private def getBlockTime4Block(b: Block): String = {
var rs = ""
private def getBlockTime4Block(b: Block): BlockTime = {
var rs = BlockTime("", "")
if (b != null && b.endorsements != null && b.endorsements.length >= 1) {
val signer = b.endorsements(0)
val date = new java.util.Date(signer.tmLocal.get.seconds * 1000);
val formatstr = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
formatstr.setTimeZone(java.util.TimeZone.getTimeZone("ETC/GMT-8"))
val tmpstr = formatstr.format(date)
rs = tmpstr + "."+signer.tmLocal.get.nanos/1000000
val createTime = tmpstr + "."+signer.tmLocal.get.nanos/1000000
// 13,毫秒精度级(utc时间)
val createTimeUtc = String.valueOf(signer.tmLocal.get.seconds * 1000 - 8 * 3600 * 1000)
rs = BlockTime(createTime, createTimeUtc)
}
rs
}