mirror of
https://gitee.com/BTAJL/repchain.git
synced 2024-12-02 19:58:55 +08:00
Merge remote-tracking branch 'origin/c4w_preview' into dev_jby_preview
This commit is contained in:
commit
65f2ec833b
@ -44,7 +44,7 @@ import rep.utils.GlobalUtils.ActorType
|
||||
import akka.actor.Props
|
||||
import rep.crypto.cert.SignTool
|
||||
import rep.log.trace._
|
||||
import rep.sc.contract.ActionResult
|
||||
import rep.sc.scalax.ActionResult
|
||||
import rep.app.conf.SystemProfile
|
||||
/**
|
||||
* RestActor伴生object,包含可接受的传入消息定义,以及处理的返回结果定义。
|
||||
|
@ -36,7 +36,7 @@ import Shim._
|
||||
import rep.crypto.BytesHex
|
||||
import rep.network.tools.PeerExtension
|
||||
import rep.storage.IdxPrefix.WorldStateKeyPreFix
|
||||
import rep.sc.contract.ActionResult
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/** 合约容器的抽象类伴生对象,定义了交易执行结果的case类
|
||||
*
|
||||
|
@ -37,7 +37,6 @@ import rep.api.rest.RestActor.loadTransaction
|
||||
import rep.network.tools.PeerExtension
|
||||
import rep.sc.js.SandboxJS
|
||||
import rep.sc.scalax.SandboxScala
|
||||
import rep.sc.contract._
|
||||
import rep.utils.SerializeUtils.deserialise
|
||||
import rep.utils.SerializeUtils.serialise
|
||||
|
||||
|
@ -30,7 +30,7 @@ import rep.sc.Shim.Oper
|
||||
import com.google.protobuf.ByteString
|
||||
import org.json4s._
|
||||
import rep.log.trace.{RepLogger,ModuleType}
|
||||
import rep.sc.contract.ActionResult
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* @author c4w
|
||||
|
@ -14,25 +14,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc.contract
|
||||
package rep.sc.scalax
|
||||
|
||||
|
||||
import scala.tools.nsc.{Global, Settings}
|
||||
import scala.reflect.internal.util.BatchSourceFile
|
||||
import tools.nsc.io.{VirtualDirectory, AbstractFile}
|
||||
import scala.reflect.internal.util.AbstractFileClassLoader
|
||||
import java.security.MessageDigest
|
||||
import java.math.BigInteger
|
||||
import collection.mutable
|
||||
import java.io._
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import rep.crypto.Sha256
|
||||
|
||||
import rep.app.conf.SystemProfile
|
||||
import scala.reflect.runtime.currentMirror
|
||||
import scala.tools.reflect.ToolBox
|
||||
import rep.storage.util.pathUtil
|
||||
import scala.reflect.io.Path.jfile2path
|
||||
|
||||
/**
|
||||
* 动态编译工具类的伴生对象,提供静态方法
|
@ -14,10 +14,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc.contract
|
||||
package rep.sc.scalax
|
||||
|
||||
import rep.protos.peer.Transaction
|
||||
import rep.sc.Sandbox.DoTransactionResult
|
||||
import rep.sc.Shim
|
||||
|
||||
class ContractContext(val api:Shim, val t:Transaction)
|
@ -29,7 +29,6 @@ import org.slf4j.LoggerFactory
|
||||
import rep.sc.Shim.Oper
|
||||
import org.json4s._
|
||||
import rep.log.trace.{RepLogger,ModuleType}
|
||||
import rep.sc.contract._
|
||||
import rep.utils.SerializeUtils.deserialise
|
||||
import rep.utils.SerializeUtils.serialise
|
||||
|
||||
|
@ -19,10 +19,15 @@ package rep.sc.tpl
|
||||
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import rep.sc.contract._
|
||||
import rep.app.conf.SystemProfile
|
||||
import rep.protos.peer.ChaincodeId
|
||||
import rep.utils.IdTool
|
||||
import rep.sc.scalax.IContract
|
||||
|
||||
import rep.sc.scalax.ContractContext
|
||||
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* 资产管理合约
|
||||
*/
|
||||
@ -39,7 +44,7 @@ class ContractAssetsTPL extends IContract{
|
||||
implicit val formats = DefaultFormats
|
||||
|
||||
def init(ctx: ContractContext){
|
||||
println(s"tid: $ctx.t.txid")
|
||||
println(s"tid: $ctx.t.id")
|
||||
}
|
||||
|
||||
def set(ctx: ContractContext, data:Map[String,Int]) :ActionResult={
|
||||
|
97
src/main/scala/rep/sc/tpl/ContractAssetsTPL2.scala
Normal file
97
src/main/scala/rep/sc/tpl/ContractAssetsTPL2.scala
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
/*
|
||||
* Copyright 2018 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BA SIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc.tpl
|
||||
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import rep.app.conf.SystemProfile
|
||||
import rep.protos.peer.ChaincodeId
|
||||
import rep.utils.IdTool
|
||||
import java.text.SimpleDateFormat
|
||||
import rep.sc.scalax.IContract
|
||||
|
||||
import rep.sc.scalax.ContractContext
|
||||
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* 资产管理合约
|
||||
*/
|
||||
|
||||
|
||||
class ContractAssetsTPL2 extends IContract{
|
||||
case class Transfer(from:String, to:String, amount:Int)
|
||||
|
||||
// 需要跨合约读账户
|
||||
val chaincodeName = SystemProfile.getAccountChaincodeName
|
||||
val chaincodeVersion = SystemProfile.getAccountChaincodeVersion
|
||||
//val prefix = IdTool.getCid(ChaincodeId(chaincodeName, chaincodeVersion))
|
||||
|
||||
implicit val formats = DefaultFormats
|
||||
|
||||
def init(ctx: ContractContext){
|
||||
println(s"tid: $ctx.t.id")
|
||||
}
|
||||
|
||||
def set(ctx: ContractContext, data:Map[String,Int]) :ActionResult={
|
||||
println(s"set data:$data")
|
||||
for((k,v)<-data){
|
||||
ctx.api.setVal(k, v)
|
||||
}
|
||||
new ActionResult(1,None)
|
||||
}
|
||||
|
||||
def transfer(ctx: ContractContext, data:Transfer) :ActionResult={
|
||||
if(!data.from.equals(ctx.t.getSignature.getCertId.creditCode))
|
||||
return new ActionResult(-1, Some("只允许从本人账户转出"))
|
||||
val signerKey = data.to
|
||||
// 跨合约读账户,该处并未反序列化
|
||||
if(ctx.api.getStateEx(chaincodeName,data.to)==null)
|
||||
return new ActionResult(-2, Some("目标账户不存在"))
|
||||
val sfrom = ctx.api.getVal(data.from)
|
||||
var dfrom =sfrom.asInstanceOf[Int]
|
||||
if(dfrom < data.amount)
|
||||
return new ActionResult(-3, Some("余额不足"))
|
||||
var dto = ctx.api.getVal(data.to).toString.toInt
|
||||
|
||||
val df:SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
|
||||
val t1 = System.currentTimeMillis()
|
||||
val s1 = s"setval begin:${ctx.t.id} " + df.format(t1)
|
||||
|
||||
ctx.api.setVal(data.from,dfrom - data.amount)
|
||||
//for test 同合约交易串行测试
|
||||
Thread.sleep(5000)
|
||||
ctx.api.setVal(data.to,dto + data.amount)
|
||||
val t2 = System.currentTimeMillis()
|
||||
val s2 = s"setval end:${ctx.t.id} " + df.format(t2)
|
||||
new ActionResult(1,Some(s1+"\n"+s2) )
|
||||
}
|
||||
/**
|
||||
* 根据action,找到对应的method,并将传入的json字符串parse为method需要的传入参数
|
||||
*/
|
||||
def onAction(ctx: ContractContext,action:String, sdata:String ):ActionResult={
|
||||
val json = parse(sdata)
|
||||
action match {
|
||||
case "transfer" =>
|
||||
transfer(ctx,json.extract[Transfer])
|
||||
case "set" =>
|
||||
set(ctx, json.extract[Map[String,Int]])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
102
src/main/scala/rep/sc/tpl/ContractAssets_Legal.scala
Normal file
102
src/main/scala/rep/sc/tpl/ContractAssets_Legal.scala
Normal file
@ -0,0 +1,102 @@
|
||||
|
||||
/*
|
||||
* Copyright 2018 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BA SIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc.tpl
|
||||
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import rep.app.conf.SystemProfile
|
||||
import rep.protos.peer.ChaincodeId
|
||||
import rep.utils.IdTool
|
||||
import java.text.SimpleDateFormat
|
||||
import rep.sc.scalax.IContract
|
||||
|
||||
import rep.sc.scalax.ContractContext
|
||||
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* 资产管理合约
|
||||
*/
|
||||
|
||||
|
||||
class ContractAssetsTPL_Legal extends IContract{
|
||||
case class Transfer(from:String, to:String, amount:Int, remind:String)
|
||||
|
||||
// 需要跨合约读账户
|
||||
val chaincodeName = SystemProfile.getAccountChaincodeName
|
||||
val chaincodeVersion = SystemProfile.getAccountChaincodeVersion
|
||||
//val prefix = IdTool.getCid(ChaincodeId(chaincodeName, chaincodeVersion))
|
||||
|
||||
implicit val formats = DefaultFormats
|
||||
|
||||
def init(ctx: ContractContext){
|
||||
println(s"tid: $ctx.t.id")
|
||||
}
|
||||
|
||||
def set(ctx: ContractContext, data:Map[String,Int]) :ActionResult={
|
||||
println(s"set data:$data")
|
||||
for((k,v)<-data){
|
||||
ctx.api.setVal(k, v)
|
||||
}
|
||||
new ActionResult(1,None)
|
||||
}
|
||||
|
||||
def transfer(ctx: ContractContext, data:Transfer) :ActionResult={
|
||||
if(!data.from.equals(ctx.t.getSignature.getCertId.creditCode))
|
||||
return new ActionResult(-1, Some("只允许从本人账户转出"))
|
||||
val signerKey = data.to
|
||||
// 跨合约读账户,该处并未反序列化
|
||||
if(ctx.api.getStateEx(chaincodeName,data.to)==null)
|
||||
return new ActionResult(-2, Some("目标账户不存在"))
|
||||
|
||||
val sfrom = ctx.api.getVal(data.from)
|
||||
var dfrom =sfrom.asInstanceOf[Int]
|
||||
if(dfrom < data.amount)
|
||||
return new ActionResult(-3, Some("余额不足"))
|
||||
|
||||
val rstr = s"""确定签名从本人所持有的账户【${data.from}】
|
||||
向账户【${data.to}】
|
||||
转账【${data.amount}】元"""
|
||||
//预执行获得结果提醒
|
||||
if(data.remind==null){
|
||||
new ActionResult(2,Some(rstr))
|
||||
}else{
|
||||
if(!data.remind.equals(rstr))
|
||||
new ActionResult(-4,Some("提醒内容不符"))
|
||||
else{
|
||||
var dto = ctx.api.getVal(data.to).toString.toInt
|
||||
ctx.api.setVal(data.from,dfrom - data.amount)
|
||||
ctx.api.setVal(data.to,dto + data.amount)
|
||||
new ActionResult(1,None)
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 根据action,找到对应的method,并将传入的json字符串parse为method需要的传入参数
|
||||
*/
|
||||
def onAction(ctx: ContractContext,action:String, sdata:String ):ActionResult={
|
||||
val json = parse(sdata)
|
||||
action match {
|
||||
case "transfer" =>
|
||||
transfer(ctx,json.extract[Transfer])
|
||||
case "set" =>
|
||||
set(ctx, json.extract[Map[String,Int]])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package rep.sc.tpl
|
||||
|
||||
import rep.sc.contract._
|
||||
import rep.protos.peer._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
|
||||
@ -8,6 +7,9 @@ import scala.collection.mutable.Map
|
||||
import org.json4s.DefaultFormats
|
||||
import rep.app.conf.SystemProfile
|
||||
import rep.utils.{IdTool, SerializeUtils}
|
||||
import rep.sc.scalax.IContract
|
||||
import rep.sc.scalax.ContractContext
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* @author zyf
|
||||
@ -146,7 +148,7 @@ class ContractCert extends IContract {
|
||||
}
|
||||
|
||||
def init(ctx: ContractContext){
|
||||
println(s"tid: $ctx.t.txid")
|
||||
println(s"tid: $ctx.t.id")
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
package rep.sc.tpl
|
||||
|
||||
import rep.sc.contract._
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import scala.reflect.ManifestFactory.classType
|
||||
@ -28,6 +27,9 @@ import org.json4s.native.Serialization.{read, write}
|
||||
import org.json4s.{DefaultFormats, Formats, jackson}
|
||||
|
||||
import rep.sc.tpl.SupplyType._
|
||||
import rep.sc.scalax.IContract
|
||||
import rep.sc.scalax.ContractContext
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* 供应链分账合约
|
||||
@ -40,7 +42,7 @@ class SupplyTPL extends IContract {
|
||||
|
||||
|
||||
def init(ctx: ContractContext){
|
||||
println(s"tid: $ctx.t.txid")
|
||||
println(s"tid: $ctx.t.id")
|
||||
}
|
||||
|
||||
/**
|
||||
|
206
src/main/scala/rep/sc/tpl/SupplyTPL2.scala
Normal file
206
src/main/scala/rep/sc/tpl/SupplyTPL2.scala
Normal file
@ -0,0 +1,206 @@
|
||||
|
||||
|
||||
/*
|
||||
* Copyright 2018 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BA SIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc.tpl
|
||||
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import scala.reflect.ManifestFactory.classType
|
||||
import scala.collection.mutable.Map
|
||||
import org.json4s.native.Serialization
|
||||
import org.json4s.native.Serialization.{read, write}
|
||||
import org.json4s.{DefaultFormats, Formats, jackson}
|
||||
|
||||
import rep.sc.tpl.SupplyType._
|
||||
import rep.sc.scalax.IContract
|
||||
import rep.sc.scalax.ContractContext
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* 供应链分账合约
|
||||
*/
|
||||
class SupplyTPL2 extends IContract {
|
||||
|
||||
val SPLIT_CHAR = "_";
|
||||
val TPL_MODE = "_PM";
|
||||
implicit val formats = DefaultFormats
|
||||
|
||||
|
||||
def init(ctx: ContractContext){
|
||||
println(s"tid: $ctx.t.id")
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加确认签名 TODO 逻辑实现
|
||||
*/
|
||||
def confirmSign(ctx: ContractContext, data:IPTConfirm ):ActionResult={
|
||||
ActionResult(1,None)
|
||||
}
|
||||
/**
|
||||
* 取消追加确认签名 TODO 逻辑实现
|
||||
*/
|
||||
def cancelSign(ctx: ContractContext, data:IPTConfirm ):ActionResult={
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param ctx
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
def SignUp(ctx: ContractContext, data:Map[String,String]):ActionResult = {
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设计方、原料方、生产方、销售方 签订对销售额的分成合约, 对于销售方账号+产品型号决定唯一的分账合约
|
||||
*/
|
||||
def signShare(ctx: ContractContext, data:IPTSignShare ):ActionResult={
|
||||
val sid = data.account_sale +SPLIT_CHAR + data.product_id
|
||||
val pid = sid+TPL_MODE
|
||||
//签约输入持久化,默认的类型转换无法胜任,以json字符串形式持久化
|
||||
ctx.api.setVal(sid, write(data))
|
||||
ctx.api.setVal(pid, TPL.Share)
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
def signFixed(ctx: ContractContext, data:IPTSignFixed ):ActionResult={
|
||||
val sid = data.account_sale +SPLIT_CHAR + data.product_id
|
||||
val pid = sid+TPL_MODE
|
||||
//签约输入持久化
|
||||
ctx.api.setVal(sid, write(data))
|
||||
ctx.api.setVal(pid, TPL.Fixed)
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账的调度方法,负责根据调用相应的分账模版, 传入模版定制参数和销售数据,进行分账
|
||||
*/
|
||||
def split(ctx: ContractContext, data:IPTSplit ):ActionResult={
|
||||
//根据销售方账号和产品Id获得分账脚本
|
||||
val sid = data.account_sale +SPLIT_CHAR + data.product_id
|
||||
val pid = sid + TPL_MODE
|
||||
val tm = ctx.api.getVal(pid).asInstanceOf[String]
|
||||
|
||||
//根据签约时选择的分账方式模版,验证定制参数
|
||||
val mr = tm match {
|
||||
case TPL.Share =>
|
||||
val sp0 = ctx.api.getVal(sid)
|
||||
val sp = read[IPTSignShare](ctx.api.getVal(sid).asInstanceOf[String])
|
||||
splitShare(data.amount, sp.account_remain, sp.tpl_param)
|
||||
case TPL.Fixed =>
|
||||
val sp = read[IPTSignFixed](ctx.api.getVal(sid).asInstanceOf[String])
|
||||
splitFixedRatio(data.amount, sp.account_remain, sp.ratio)
|
||||
}
|
||||
//返回分账计算结果
|
||||
addToAccount(ctx, mr)
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将分账结果增加到账户并持久化
|
||||
*/
|
||||
def addToAccount(ctx: ContractContext, mr:Map[String,Int]){
|
||||
for ((k, v) <- mr) {
|
||||
val sk = ctx.api.getVal(k)
|
||||
var dk = if(sk==null) 0 else sk.toString.toInt
|
||||
ctx.api.setVal(k, dk+v)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 合约方法入口
|
||||
*/
|
||||
def onAction(ctx: ContractContext,action:String, sdata:String ):ActionResult={
|
||||
val json = parse(sdata)
|
||||
|
||||
action match {
|
||||
//for test 合约升级变体
|
||||
//case ACTION.SignShare =>
|
||||
// signShare(ctx,json.extract[IPTSignShare])
|
||||
case ACTION.SignFixed =>
|
||||
signFixed(ctx,json.extract[IPTSignFixed])
|
||||
case ACTION.Split =>
|
||||
split(ctx, json.extract[IPTSplit])
|
||||
case ACTION.ConfirmSign =>
|
||||
confirmSign(ctx,json.extract[IPTConfirm])
|
||||
case ACTION.CancelSign =>
|
||||
cancelSign(ctx, json.extract[IPTConfirm])
|
||||
case ACTION.SignUp =>
|
||||
println(s"SignUp")
|
||||
SignUp(ctx, json.extract[Map[String,String]])
|
||||
|
||||
}
|
||||
}
|
||||
//TODO case Transaction.Type.CHAINCODE_DESC 增加对合约描述的处理
|
||||
def descAction(ctx: ContractContext,action:String, sdata:String ):String={
|
||||
val json = parse(sdata)
|
||||
null
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部函数, 获得分阶段的分成
|
||||
*/
|
||||
def getShare(sr: Int, ar: Array[ShareRatio]) : Int={
|
||||
var rv = 0
|
||||
for(el <- ar) {
|
||||
//击中金额范围
|
||||
if(sr > el.from && sr <= el.to) {
|
||||
//固定金额
|
||||
if(el.fixed > 0)
|
||||
rv = el.fixed
|
||||
else //按比例分成
|
||||
rv = (sr * el.ratio) .toInt
|
||||
}
|
||||
}
|
||||
rv
|
||||
}
|
||||
/**
|
||||
* 合约中内置多种分账模版,签约时可选择模版,如果出现新的分账模版,则部署一版新的合约
|
||||
* 分成模型, 除了销售方之外, 其他各方要求一个最低金额,分成按照金额阶段有所不同。
|
||||
*/
|
||||
def splitShare(sr: Int, account_remain:String, rule: ShareMap): Map[String,Int] ={
|
||||
//分账结果
|
||||
val rm : Map[String, Int] = Map()
|
||||
//分账余额
|
||||
var remain = sr
|
||||
for ((k, v) <- rule) {
|
||||
val rv = getShare(sr, v)
|
||||
rm += (k -> rv)
|
||||
remain -= rv
|
||||
}
|
||||
rm += (account_remain -> remain)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 各方固定比例分成,此模版仅仅为了合约对多模版的支持,可能无实际用途
|
||||
*/
|
||||
def splitFixedRatio(sr: Int, account_remain: String, mr:FixedMap): Map[String,Int] ={
|
||||
val rm : Map[String, Int] = Map()
|
||||
var remain = sr
|
||||
//根据固定分成
|
||||
for ((k, v) <- mr) {
|
||||
val rv = (sr* v ).toInt
|
||||
rm += (k -> rv)
|
||||
remain -= rv
|
||||
}
|
||||
//剩余的分给指定的余额账户
|
||||
rm += (account_remain -> remain)
|
||||
}
|
||||
}
|
206
src/main/scala/rep/sc/tpl/SupplyTPL3.scala
Normal file
206
src/main/scala/rep/sc/tpl/SupplyTPL3.scala
Normal file
@ -0,0 +1,206 @@
|
||||
|
||||
|
||||
/*
|
||||
* Copyright 2018 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BA SIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc.tpl
|
||||
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import scala.reflect.ManifestFactory.classType
|
||||
import scala.collection.mutable.Map
|
||||
import org.json4s.native.Serialization
|
||||
import org.json4s.native.Serialization.{read, write}
|
||||
import org.json4s.{DefaultFormats, Formats, jackson}
|
||||
|
||||
import rep.sc.tpl.SupplyType._
|
||||
import rep.sc.scalax.IContract
|
||||
import rep.sc.scalax.ContractContext
|
||||
import rep.sc.scalax.ActionResult
|
||||
|
||||
/**
|
||||
* 供应链分账合约
|
||||
*/
|
||||
class SupplyTPL3 extends IContract {
|
||||
|
||||
val SPLIT_CHAR = "_";
|
||||
val TPL_MODE = "_PM";
|
||||
implicit val formats = DefaultFormats
|
||||
|
||||
|
||||
def init(ctx: ContractContext){
|
||||
println(s"tid: $ctx.t.id")
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加确认签名 TODO 逻辑实现
|
||||
*/
|
||||
def confirmSign(ctx: ContractContext, data:IPTConfirm ):ActionResult={
|
||||
ActionResult(1,None)
|
||||
}
|
||||
/**
|
||||
* 取消追加确认签名 TODO 逻辑实现
|
||||
*/
|
||||
def cancelSign(ctx: ContractContext, data:IPTConfirm ):ActionResult={
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param ctx
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
def SignUp(ctx: ContractContext, data:Map[String,String]):ActionResult = {
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设计方、原料方、生产方、销售方 签订对销售额的分成合约, 对于销售方账号+产品型号决定唯一的分账合约
|
||||
*/
|
||||
def signShare(ctx: ContractContext, data:IPTSignShare ):ActionResult={
|
||||
val sid = data.account_sale +SPLIT_CHAR + data.product_id
|
||||
val pid = sid+TPL_MODE
|
||||
//签约输入持久化,默认的类型转换无法胜任,以json字符串形式持久化
|
||||
ctx.api.setVal(sid, write(data))
|
||||
ctx.api.setVal(pid, TPL.Share)
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
def signFixed(ctx: ContractContext, data:IPTSignFixed ):ActionResult={
|
||||
val sid = data.account_sale +SPLIT_CHAR + data.product_id
|
||||
val pid = sid+TPL_MODE
|
||||
//签约输入持久化
|
||||
ctx.api.setVal(sid, write(data))
|
||||
ctx.api.setVal(pid, TPL.Fixed)
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账的调度方法,负责根据调用相应的分账模版, 传入模版定制参数和销售数据,进行分账
|
||||
*/
|
||||
def split(ctx: ContractContext, data:IPTSplit ):ActionResult={
|
||||
//根据销售方账号和产品Id获得分账脚本
|
||||
val sid = data.account_sale +SPLIT_CHAR + data.product_id
|
||||
val pid = sid + TPL_MODE
|
||||
val tm = ctx.api.getVal(pid).asInstanceOf[String]
|
||||
|
||||
//根据签约时选择的分账方式模版,验证定制参数
|
||||
val mr = tm match {
|
||||
case TPL.Share =>
|
||||
val sp0 = ctx.api.getVal(sid)
|
||||
val sp = read[IPTSignShare](ctx.api.getVal(sid).asInstanceOf[String])
|
||||
splitShare(data.amount, sp.account_remain, sp.tpl_param)
|
||||
case TPL.Fixed =>
|
||||
val sp = read[IPTSignFixed](ctx.api.getVal(sid).asInstanceOf[String])
|
||||
splitFixedRatio(data.amount, sp.account_remain, sp.ratio)
|
||||
}
|
||||
//返回分账计算结果
|
||||
addToAccount(ctx, mr)
|
||||
ActionResult(1,None)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将分账结果增加到账户并持久化
|
||||
*/
|
||||
def addToAccount(ctx: ContractContext, mr:Map[String,Int]){
|
||||
for ((k, v) <- mr) {
|
||||
val sk = ctx.api.getVal(k)
|
||||
var dk = if(sk==null) 0 else sk.toString.toInt
|
||||
ctx.api.setVal(k, dk+v)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 合约方法入口
|
||||
*/
|
||||
def onAction(ctx: ContractContext,action:String, sdata:String ):ActionResult={
|
||||
val json = parse(sdata)
|
||||
|
||||
action match {
|
||||
case ACTION.SignShare =>
|
||||
signShare(ctx,json.extract[IPTSignShare])
|
||||
//for test 合约升级变体
|
||||
//case ACTION.SignFixed =>
|
||||
// signFixed(ctx,json.extract[IPTSignFixed])
|
||||
case ACTION.Split =>
|
||||
split(ctx, json.extract[IPTSplit])
|
||||
case ACTION.ConfirmSign =>
|
||||
confirmSign(ctx,json.extract[IPTConfirm])
|
||||
case ACTION.CancelSign =>
|
||||
cancelSign(ctx, json.extract[IPTConfirm])
|
||||
case ACTION.SignUp =>
|
||||
println(s"SignUp")
|
||||
SignUp(ctx, json.extract[Map[String,String]])
|
||||
|
||||
}
|
||||
}
|
||||
//TODO case Transaction.Type.CHAINCODE_DESC 增加对合约描述的处理
|
||||
def descAction(ctx: ContractContext,action:String, sdata:String ):String={
|
||||
val json = parse(sdata)
|
||||
null
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部函数, 获得分阶段的分成
|
||||
*/
|
||||
def getShare(sr: Int, ar: Array[ShareRatio]) : Int={
|
||||
var rv = 0
|
||||
for(el <- ar) {
|
||||
//击中金额范围
|
||||
if(sr > el.from && sr <= el.to) {
|
||||
//固定金额
|
||||
if(el.fixed > 0)
|
||||
rv = el.fixed
|
||||
else //按比例分成
|
||||
rv = (sr * el.ratio) .toInt
|
||||
}
|
||||
}
|
||||
rv
|
||||
}
|
||||
/**
|
||||
* 合约中内置多种分账模版,签约时可选择模版,如果出现新的分账模版,则部署一版新的合约
|
||||
* 分成模型, 除了销售方之外, 其他各方要求一个最低金额,分成按照金额阶段有所不同。
|
||||
*/
|
||||
def splitShare(sr: Int, account_remain:String, rule: ShareMap): Map[String,Int] ={
|
||||
//分账结果
|
||||
val rm : Map[String, Int] = Map()
|
||||
//分账余额
|
||||
var remain = sr
|
||||
for ((k, v) <- rule) {
|
||||
val rv = getShare(sr, v)
|
||||
rm += (k -> rv)
|
||||
remain -= rv
|
||||
}
|
||||
rm += (account_remain -> remain)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 各方固定比例分成,此模版仅仅为了合约对多模版的支持,可能无实际用途
|
||||
*/
|
||||
def splitFixedRatio(sr: Int, account_remain: String, mr:FixedMap): Map[String,Int] ={
|
||||
val rm : Map[String, Int] = Map()
|
||||
var remain = sr
|
||||
//根据固定分成
|
||||
for ((k, v) <- mr) {
|
||||
val rv = (sr* v ).toInt
|
||||
rm += (k -> rv)
|
||||
remain -= rv
|
||||
}
|
||||
//剩余的分给指定的余额账户
|
||||
rm += (account_remain -> remain)
|
||||
}
|
||||
}
|
@ -37,7 +37,6 @@ import rep.utils.SerializeUtils.deserialise
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
import rep.sc.contract._
|
||||
import java.io.IOException
|
||||
import java.io.PrintWriter
|
||||
import java.io.FileWriter
|
||||
|
@ -37,7 +37,6 @@ import rep.utils.SerializeUtils.deserialise
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
import rep.sc.contract._
|
||||
import java.io.IOException
|
||||
import java.io.PrintWriter
|
||||
import java.io.FileWriter
|
||||
|
210
src/test/scala/rep/sc/SupplySpec2.scala
Normal file
210
src/test/scala/rep/sc/SupplySpec2.scala
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2018 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BA SIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc
|
||||
|
||||
import org.scalatest.{ BeforeAndAfterAll, FlatSpecLike, Matchers }
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.TestKit
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import rep.protos.peer._
|
||||
import rep.sc.Sandbox._
|
||||
import rep.app.system.ClusterSystem
|
||||
import rep.app.system.ClusterSystem.InitType
|
||||
|
||||
import rep.network.PeerHelper
|
||||
import org.json4s.{ DefaultFormats, jackson }
|
||||
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
|
||||
import org.json4s._
|
||||
import rep.network.module.ModuleManager
|
||||
import rep.storage.ImpDataAccess
|
||||
import rep.utils.SerializeUtils.deserialise
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.PrintWriter
|
||||
import java.io.FileWriter
|
||||
import java.io.File
|
||||
|
||||
import scala.collection.mutable.Map
|
||||
import org.json4s.{DefaultFormats, Formats, jackson}
|
||||
import org.json4s.native.Serialization.writePretty
|
||||
import org.json4s.native.Serialization
|
||||
import org.json4s.native.Serialization.{read, write}
|
||||
|
||||
/** 合约容器实现的单元测试
|
||||
* @author c4w
|
||||
* @param _system 测试用例所在的actor System.
|
||||
*
|
||||
*/
|
||||
class SupplySpec2(_system: ActorSystem)
|
||||
extends TestKit(_system)
|
||||
with Matchers
|
||||
with FlatSpecLike
|
||||
with BeforeAndAfterAll {
|
||||
|
||||
import rep.sc.TransProcessor.DoTransaction
|
||||
import rep.sc.Sandbox.DoTransactionResult
|
||||
|
||||
import akka.testkit.TestProbe
|
||||
import akka.testkit.TestActorRef
|
||||
import Json4sSupport._
|
||||
import rep.sc.tpl.SupplyType._
|
||||
import rep.utils.SerializeUtils.toJson
|
||||
|
||||
implicit val serialization = jackson.Serialization
|
||||
// or native.Serialization
|
||||
implicit val formats = DefaultFormats
|
||||
|
||||
def this() = this(ActorSystem("SandBoxSpec", new ClusterSystem("121000005l35120456.node1", InitType.MULTI_INIT, false).getConf))
|
||||
|
||||
override def afterAll: Unit = Await.ready(system.terminate(), Duration.Inf)
|
||||
|
||||
//Scala实现的资产管理合约测试,包括合约的部署、调用、结果返回验证
|
||||
"container" should "update contract & share kv" in {
|
||||
val sysName = "121000005l35120456.node1"
|
||||
val dbTag = "121000005l35120456.node1"
|
||||
//建立PeerManager实例是为了调用transactionCreator(需要用到密钥签名),无他
|
||||
val pm = system.actorOf(ModuleManager.props("pm", sysName))
|
||||
//加载合约脚本
|
||||
val s1 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/SupplyTPL2.scala")
|
||||
val l1 = try s1.mkString finally s1.close()
|
||||
|
||||
val s7 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/SupplyTPL3.scala")
|
||||
val l7 = try s7.mkString finally s7.close()
|
||||
|
||||
val fm :FixedMap= Map("A" -> 0.2, "B"-> 0.2, "C"-> 0.1, "D" -> 0.1)
|
||||
val sm :ShareMap = Map("A" -> Array(new ShareRatio(0,100,0.1,0), new ShareRatio(100,10000,0.15,0)),
|
||||
"B" -> Array(new ShareRatio(0,10000,0,10)),
|
||||
"C" -> Array(new ShareRatio(0,10000,0.1,0)),
|
||||
"D" -> Array(new ShareRatio(0,100,0,10), new ShareRatio(100,10000,0.15,0)))
|
||||
val account_remain = "R"
|
||||
val account_sales1 = "S1"
|
||||
val account_sales2 = "S2"
|
||||
val product_id = "P201806270001"
|
||||
|
||||
//构造签约交易合约模版1输入json字符串,销售1选择了合约模版1
|
||||
val ipt2 = new IPTSignFixed(account_sales1,product_id,account_remain,fm)
|
||||
val l2 = write(ipt2)
|
||||
|
||||
//构造签约交易合约模版2输入json字符串,,销售2选择了合约模版2
|
||||
val ipt3 = new IPTSignShare(account_sales2,product_id,account_remain,sm)
|
||||
val l3 = writePretty(ipt3)
|
||||
|
||||
//准备探针以验证调用返回结果
|
||||
val probe = TestProbe()
|
||||
val db = ImpDataAccess.GetDataAccess(sysName)
|
||||
var sandbox = system.actorOf(TransProcessor.props("sandbox", "", probe.ref))
|
||||
//生成deploy交易
|
||||
val cid = new ChaincodeId("Supply",1)
|
||||
val t1 = PeerHelper.createTransaction4Deploy(sysName, cid,
|
||||
l1, "",5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA)
|
||||
|
||||
val msg_send1 = new DoTransaction(t1, probe.ref, "")
|
||||
probe.send(sandbox, msg_send1)
|
||||
val msg_recv1 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
val ol1 = msg_recv1.ol
|
||||
|
||||
//生成invoke交易
|
||||
//获取deploy生成的chainCodeId
|
||||
//初始化资产
|
||||
val t2 = PeerHelper.createTransaction4Invoke(sysName,cid, ACTION.SignFixed, Seq(l2))
|
||||
|
||||
val msg_send2 = new DoTransaction(t2, probe.ref, "")
|
||||
probe.send(sandbox, msg_send2)
|
||||
val msg_recv2 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
//由于版本1支持SignFixed 分账方法,因此能够正确处理
|
||||
msg_recv2.r.code should be (1)
|
||||
|
||||
var t = PeerHelper.createTransaction4Invoke(sysName, cid, ACTION.SignShare, Seq(l3))
|
||||
var msg_send = new DoTransaction(t, probe.ref, "")
|
||||
probe.send(sandbox, msg_send)
|
||||
var msg_recv = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
//由于版本1不支持SignShare 分账方法,因此无法正确处理
|
||||
msg_recv.err should not be None
|
||||
|
||||
|
||||
//部署版本2
|
||||
val cid2 = new ChaincodeId("Supply",2)
|
||||
t = PeerHelper.createTransaction4Deploy(sysName, cid2,
|
||||
l7, "",5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA)
|
||||
msg_send = new DoTransaction(t, probe.ref, "")
|
||||
probe.send(sandbox, msg_send)
|
||||
msg_recv = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv.r.code should be (1)
|
||||
|
||||
t = PeerHelper.createTransaction4Invoke(sysName, cid2, ACTION.SignShare, Seq(l3))
|
||||
msg_send = new DoTransaction(t, probe.ref, "")
|
||||
probe.send(sandbox, msg_send)
|
||||
msg_recv = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
//由于版本2支持SignShare 分账方法,因此正确处理
|
||||
msg_recv.r.code should be (1)
|
||||
|
||||
|
||||
//测试各种金额下的分账结果
|
||||
val sr = Array(100, 200, 500, 1000)
|
||||
for (el<- sr) {
|
||||
//构造分账交易
|
||||
val ipt4 = new IPTSplit(account_sales1,product_id,el)
|
||||
val l4 = write(ipt4)
|
||||
val t4 = PeerHelper.createTransaction4Invoke(sysName, cid, ACTION.Split, Seq(l4))
|
||||
val msg_send4 = new DoTransaction(t4, probe.ref, "")
|
||||
|
||||
probe.send(sandbox, msg_send4)
|
||||
val msg_recv4 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
val ol4 = msg_recv4.ol
|
||||
val ol4str = toJson(ol4)
|
||||
println(s"oper log:${ol4str}")
|
||||
//分账之后总额应保持一致
|
||||
var total = 0
|
||||
ol4.foreach {
|
||||
ol =>
|
||||
total += deserialise(ol.newValue).asInstanceOf[Int]
|
||||
if(ol.oldValue!= null)
|
||||
total -= deserialise(ol.oldValue).asInstanceOf[Int]
|
||||
}
|
||||
total should be(el)
|
||||
}
|
||||
|
||||
for (el<- sr) {
|
||||
//构造分账交易
|
||||
val ipt4 = new IPTSplit(account_sales2,product_id,el)
|
||||
val l4 = write(ipt4)
|
||||
val t4 = PeerHelper.createTransaction4Invoke(sysName, cid2, ACTION.Split, Seq(l4))
|
||||
val msg_send4 = new DoTransaction(t4, probe.ref, "")
|
||||
|
||||
probe.send(sandbox, msg_send4)
|
||||
val msg_recv4 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
val ol4 = msg_recv4.ol
|
||||
val ol4str = toJson(ol4)
|
||||
println(s"oper log:${ol4str}")
|
||||
//分账之后总额应保持一致
|
||||
var total = 0
|
||||
ol4.foreach {
|
||||
ol =>
|
||||
total += deserialise(ol.newValue).asInstanceOf[Int]
|
||||
//由于不同版本共享kv,前面的分账结果导致账户不为空
|
||||
ol.oldValue should not be null
|
||||
total -= deserialise(ol.oldValue).asInstanceOf[Int]
|
||||
}
|
||||
total should be(el)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
137
src/test/scala/rep/sc/TransferSpec2.scala
Normal file
137
src/test/scala/rep/sc/TransferSpec2.scala
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2018 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BA SIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{TestKit, TestProbe}
|
||||
import org.json4s.{DefaultFormats, jackson}
|
||||
import org.json4s.native.Serialization.{write, writePretty}
|
||||
import org.scalatest.{BeforeAndAfterAll, FlatSpecLike, Matchers}
|
||||
import rep.app.system.ClusterSystem
|
||||
import rep.app.system.ClusterSystem.InitType
|
||||
import rep.network.PeerHelper
|
||||
import rep.network.module.ModuleManager
|
||||
import rep.protos.peer.{Certificate, ChaincodeId, Signer}
|
||||
import rep.sc.TransProcessor.DoTransaction
|
||||
import rep.sc.TransferSpec.{ACTION, SetMap}
|
||||
import rep.sc.tpl.{CertInfo, Transfer}
|
||||
import rep.storage.ImpDataAccess
|
||||
import rep.utils.SerializeUtils.toJson
|
||||
import rep.app.conf.SystemProfile
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.collection.mutable.Map
|
||||
|
||||
|
||||
/**
|
||||
* author zyf
|
||||
* @param _system
|
||||
*/
|
||||
class TransferSpec2(_system: ActorSystem)
|
||||
extends TestKit(_system) with Matchers with FlatSpecLike with BeforeAndAfterAll {
|
||||
|
||||
def this() = this(ActorSystem("TransferSpec", new ClusterSystem("121000005l35120456.node1", InitType.MULTI_INIT, false).getConf))
|
||||
|
||||
override def afterAll: Unit = { shutdown(system) }
|
||||
|
||||
implicit val serialization = jackson.Serialization
|
||||
// or native.Serialization
|
||||
implicit val formats = DefaultFormats
|
||||
|
||||
"ContractAssetsTPL" should "can set assets and transfer from a to b" in {
|
||||
val sysName = "121000005l35120456.node1"
|
||||
val dbTag = "121000005l35120456.node1"
|
||||
//建立PeerManager实例是为了调用transactionCreator(需要用到密钥签名),无他
|
||||
val pm = system.actorOf(ModuleManager.props("pm", sysName))
|
||||
// 部署资产管理
|
||||
val s1 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/ContractAssetsTPL2.scala")
|
||||
val l1 = try s1.mkString finally s1.close()
|
||||
// 部署账户管理合约
|
||||
val s2 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/ContractCert.scala")
|
||||
val l2 = try s2.mkString finally s2.close()
|
||||
val sm: SetMap = Map("121000005l35120456" -> 50, "12110107bi45jh675g" -> 50, "122000002n00123567" -> 50)
|
||||
val sms = write(sm)
|
||||
|
||||
val tcs = Array(
|
||||
Transfer("121000005l35120456", "12110107bi45jh675g", 5),
|
||||
Transfer("121000005l35120456", "12110107bi45jh675g", 3),
|
||||
Transfer("121000005l35120456", "12110107bi45jh675g", 2))
|
||||
val rcs = Array(1, 1 , 1)
|
||||
|
||||
val signer = Signer("node2", "12110107bi45jh675g", "13856789234", Seq("node2"))
|
||||
val cert = scala.io.Source.fromFile("jks/certs/12110107bi45jh675g.node2.cer")
|
||||
val certStr = try cert.mkString finally cert.close()
|
||||
val certinfo = CertInfo("12110107bi45jh675g", "node2", Certificate(certStr, "SHA1withECDSA", true, None, None) )
|
||||
//准备探针以验证调用返回结果
|
||||
val probe = TestProbe()
|
||||
val db = ImpDataAccess.GetDataAccess(sysName)
|
||||
val sandbox = system.actorOf(TransProcessor.props("sandbox", "", probe.ref))
|
||||
|
||||
val cid2 = ChaincodeId(SystemProfile.getAccountChaincodeName,1)
|
||||
val cid1 = ChaincodeId("ContractAssetsTPL2",1)
|
||||
//生成deploy交易
|
||||
val t1 = PeerHelper.createTransaction4Deploy(sysName,cid1 ,
|
||||
l1, "",5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA)
|
||||
|
||||
val msg_send1 = DoTransaction(t1, probe.ref, "")
|
||||
probe.send(sandbox, msg_send1)
|
||||
val msg_recv1 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv1.r.code should be (1)
|
||||
|
||||
val t2 = PeerHelper.createTransaction4Deploy(sysName,cid2,
|
||||
l2, "",5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA)
|
||||
|
||||
val msg_send2 = DoTransaction(t2, probe.ref, "")
|
||||
probe.send(sandbox, msg_send2)
|
||||
val msg_recv2 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv2.r.code should be (1)
|
||||
|
||||
// 生成invoke交易
|
||||
// 注册账户
|
||||
val t3 = PeerHelper.createTransaction4Invoke(sysName,cid2, ACTION.SignUpSigner, Seq(write(signer)))
|
||||
val msg_send3 = DoTransaction(t3, probe.ref, "")
|
||||
probe.send(sandbox, msg_send3)
|
||||
val msg_recv3 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv3.r.code should be (1)
|
||||
|
||||
// 注册证书
|
||||
val t4 = PeerHelper.createTransaction4Invoke(sysName,cid2, ACTION.SignUpCert, Seq(writePretty(certinfo)))
|
||||
val msg_send4 = DoTransaction(t4, probe.ref, "")
|
||||
probe.send(sandbox, msg_send4)
|
||||
val msg_recv4 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv4.r.code should be (1)
|
||||
|
||||
|
||||
//生成invoke交易
|
||||
val t5 = PeerHelper.createTransaction4Invoke(sysName,cid1, ACTION.set, Seq(sms))
|
||||
val msg_send5 = DoTransaction(t5, probe.ref, "")
|
||||
probe.send(sandbox, msg_send5)
|
||||
val msg_recv5 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv5.r.code should be (1)
|
||||
|
||||
for (i <- 0 until tcs.length){
|
||||
val t6 = PeerHelper.createTransaction4Invoke(sysName, cid1, ACTION.transfer, Seq(write(tcs(i))))
|
||||
val msg_send6 = DoTransaction(t6, probe.ref, "")
|
||||
probe.send(sandbox, msg_send6)
|
||||
}
|
||||
for (i <- 0 until tcs.length){
|
||||
val msg_recv6 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv6.r.code should be (rcs(i))
|
||||
println(msg_recv6.r.reason)
|
||||
}
|
||||
}
|
||||
}
|
138
src/test/scala/rep/sc/TransferSpec_Legal.scala
Normal file
138
src/test/scala/rep/sc/TransferSpec_Legal.scala
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2018 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BA SIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package rep.sc
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{TestKit, TestProbe}
|
||||
import org.scalatest.{BeforeAndAfterAll, FlatSpecLike, Matchers}
|
||||
import rep.app.system.ClusterSystem
|
||||
import rep.app.system.ClusterSystem.InitType
|
||||
import rep.network.PeerHelper
|
||||
import rep.network.module.ModuleManager
|
||||
import rep.protos.peer.{Certificate, ChaincodeId, Signer}
|
||||
import rep.sc.TransProcessor.DoTransaction
|
||||
import rep.sc.TransferSpec.{ACTION, SetMap}
|
||||
import rep.sc.tpl.{CertInfo}
|
||||
import rep.storage.ImpDataAccess
|
||||
import rep.utils.SerializeUtils.toJson
|
||||
import rep.app.conf.SystemProfile
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.collection.mutable.Map
|
||||
|
||||
|
||||
/**
|
||||
* author zyf
|
||||
* @param _system
|
||||
*/
|
||||
class TransferSpec_Legal(_system: ActorSystem)
|
||||
extends TestKit(_system) with Matchers with FlatSpecLike with BeforeAndAfterAll {
|
||||
|
||||
case class Transfer(from:String, to:String, amount:Int, remind:String)
|
||||
|
||||
|
||||
def this() = this(ActorSystem("TransferSpec", new ClusterSystem("121000005l35120456.node1", InitType.MULTI_INIT, false).getConf))
|
||||
|
||||
override def afterAll: Unit = { shutdown(system) }
|
||||
|
||||
|
||||
"ContractAssetsTPL" should "can set assets and transfer from a to b" in {
|
||||
val sysName = "121000005l35120456.node1"
|
||||
val dbTag = "121000005l35120456.node1"
|
||||
//建立PeerManager实例是为了调用transactionCreator(需要用到密钥签名),无他
|
||||
val pm = system.actorOf(ModuleManager.props("pm", sysName))
|
||||
// 部署资产管理
|
||||
val s1 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/ContractAssets_Legal.scala")
|
||||
val l1 = try s1.mkString finally s1.close()
|
||||
// 部署账户管理合约
|
||||
val s2 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/ContractCert.scala")
|
||||
val l2 = try s2.mkString finally s2.close()
|
||||
val sm: SetMap = Map("121000005l35120456" -> 50, "12110107bi45jh675g" -> 50, "122000002n00123567" -> 50)
|
||||
val sms = toJson(sm)
|
||||
|
||||
|
||||
val signer = Signer("node2", "12110107bi45jh675g", "13856789234", Seq("node2"))
|
||||
val cert = scala.io.Source.fromFile("jks/certs/12110107bi45jh675g.node2.cer")
|
||||
val certStr = try cert.mkString finally cert.close()
|
||||
val certinfo = CertInfo("12110107bi45jh675g", "node2", Certificate(certStr, "SHA1withECDSA", true, None, None) )
|
||||
//准备探针以验证调用返回结果
|
||||
val probe = TestProbe()
|
||||
val db = ImpDataAccess.GetDataAccess(sysName)
|
||||
val sandbox = system.actorOf(TransProcessor.props("sandbox", "", probe.ref))
|
||||
|
||||
val cid2 = ChaincodeId(SystemProfile.getAccountChaincodeName,1)
|
||||
val cid1 = ChaincodeId("ContractAssetsTPL",1)
|
||||
//生成deploy交易
|
||||
val t1 = PeerHelper.createTransaction4Deploy(sysName,cid1 ,
|
||||
l1, "",5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA)
|
||||
|
||||
val msg_send1 = DoTransaction(t1, probe.ref, "")
|
||||
probe.send(sandbox, msg_send1)
|
||||
val msg_recv1 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv1.r.code should be (1)
|
||||
|
||||
val t2 = PeerHelper.createTransaction4Deploy(sysName,cid2,
|
||||
l2, "",5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA)
|
||||
|
||||
val msg_send2 = DoTransaction(t2, probe.ref, "")
|
||||
probe.send(sandbox, msg_send2)
|
||||
val msg_recv2 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv2.r.code should be (1)
|
||||
|
||||
// 生成invoke交易
|
||||
// 注册账户
|
||||
val t3 = PeerHelper.createTransaction4Invoke(sysName,cid2, ACTION.SignUpSigner, Seq(toJson(signer)))
|
||||
val msg_send3 = DoTransaction(t3, probe.ref, "")
|
||||
probe.send(sandbox, msg_send3)
|
||||
val msg_recv3 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv3.r.code should be (1)
|
||||
|
||||
// 注册证书
|
||||
val t4 = PeerHelper.createTransaction4Invoke(sysName,cid2, ACTION.SignUpCert, Seq(toJson(certinfo)))
|
||||
val msg_send4 = DoTransaction(t4, probe.ref, "")
|
||||
probe.send(sandbox, msg_send4)
|
||||
val msg_recv4 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv4.r.code should be (1)
|
||||
|
||||
|
||||
//生成invoke交易
|
||||
val t5 = PeerHelper.createTransaction4Invoke(sysName,cid1, ACTION.set, Seq(sms))
|
||||
val msg_send5 = DoTransaction(t5, probe.ref, "")
|
||||
probe.send(sandbox, msg_send5)
|
||||
val msg_recv5 = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv5.r.code should be (1)
|
||||
|
||||
//获得提醒文本
|
||||
var p = Transfer("121000005l35120456", "12110107bi45jh675g", 5,null)
|
||||
var t = PeerHelper.createTransaction4Invoke(sysName, cid1, ACTION.transfer, Seq(toJson(p)))
|
||||
var msg_send = DoTransaction(t, probe.ref, "")
|
||||
probe.send(sandbox, msg_send)
|
||||
var msg_recv = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv.r.code should be (2)
|
||||
|
||||
//对提醒文本签名
|
||||
val remind = msg_recv.r.reason.get
|
||||
println(remind)
|
||||
p = Transfer("121000005l35120456", "12110107bi45jh675g", 5,remind )
|
||||
t = PeerHelper.createTransaction4Invoke(sysName, cid1, ACTION.transfer, Seq(toJson(p)))
|
||||
msg_send = DoTransaction(t, probe.ref, "")
|
||||
probe.send(sandbox, msg_send)
|
||||
msg_recv = probe.expectMsgType[Sandbox.DoTransactionResult](1000.seconds)
|
||||
msg_recv.r.code should be (1)
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user