Merge remote-tracking branch 'origin/c4w_preview' into dev_jby_preview

This commit is contained in:
wuwei1972 2019-03-27 08:18:48 +08:00
commit 65f2ec833b
19 changed files with 1117 additions and 20 deletions

View File

@ -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包含可接受的传入消息定义以及处理的返回结果定义

View File

@ -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类
*

View File

@ -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

View File

@ -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

View File

@ -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
/**
* 动态编译工具类的伴生对象提供静态方法

View File

@ -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)

View File

@ -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

View File

@ -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={

View 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]])
}
}
}

View 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]])
}
}
}

View File

@ -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")
}

View File

@ -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")
}
/**

View 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)
}
}

View 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)
}
}

View File

@ -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

View File

@ -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

View 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)
}
}
}

View 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)
}
}
}

View 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)
}
}