原文地址:https://docs.corda.net/api-contracts.html

注意:阅读本文之前,你应该对 Corda 核心概念 - Contract 比较熟悉了。

Contract

Contracts 都是实现了 Contract 接口的类。Contract 接口定义如下:

/*** Implemented by a program that implements business logic on the shared ledger. All participants run this code for* every [net.corda.core.transactions.LedgerTransaction] they see on the network, for every input and output state. All* contracts must accept the transaction for it to be accepted: failure of any aborts the entire thing. The time is taken* from a trusted time-window attached to the transaction itself i.e. it is NOT necessarily the current time.** TODO: Contract serialization is likely to change, so the annotation is likely temporary.*/
@CordaSerializable
interface Contract {/*** Takes an object that represents a state transition, and ensures the inputs/outputs/commands make sense.* Must throw an exception if there's a problem that should prevent state transition. Takes a single object* rather than an argument so that additional data can be added without breaking binary compatibility with* existing contract code.*/@Throws(IllegalArgumentException::class)fun verify(tx: LedgerTransaction)
}

Contract 只有一个 verify 方法,它会有一个 LedgerTransaction 作为 input 参数并且不会返回任何内容。这个方法被用来检验一个交易的提议是否有效,包括下边的验证:

  • 我们会搜集这个交易的 input 和 output states 的 contract code
  • 我们会调用每个 contract code 的 verify 方法,将 transaction 作为 input 传进去
  • 这个更新账本的提议仅仅在所有的 verify 方法都没有返回 exception 的情况下才算是有效的

verify 是在一个 sandbox 中执行的:

  • 它没有权限访问内部的内容
  • 针对于它可用的类库被放入白名单来不允许:网络访问像硬盘或数据库 I/O

这意味着 verify 仅仅能够在决定一个交易是否有效的时候才能够访问 LedgerTransaction 中定义的属性。

最简单的两个 verify 方法:

  • 一个是接受所有可能的 transactions:
override fun verify(tx: TransactionForContract) {// Always accepts!
}
  • 一个是拒绝所有的 transactions:
override fun verify(tx: TransactionForContract) {throw IllegalArgumentException("Always rejects!")
}

LedgerTransaction

被传入 verify 方法中的 LedgerTransaction 对象具有以下属性:

@CordaSerializable
data class LedgerTransaction @JvmOverloads constructor(/** The resolved input states which will be consumed/invalidated by the execution of this transaction. */override val inputs: List<StateAndRef<ContractState>>,override val outputs: List<TransactionState<ContractState>>,/** Arbitrary data passed to the program of each input state. */val commands: List<CommandWithParties<CommandData>>,/** A list of [Attachment] objects identified by the transaction that are needed for this transaction to verify. */val attachments: List<Attachment>,/** The hash of the original serialised WireTransaction. */override val id: SecureHash,override val notary: Party?,val timeWindow: TimeWindow?,val privacySalt: PrivacySalt,private val networkParameters: NetworkParameters? = null
) : FullTransaction() {

其中:

  • inputs 是类型为 List<StateAndRef<ContractState>> 的 transaction 的 inputs
  • outputs 是类型为 List<TransactionState<ContractState>> 的 transaction 的 outputs
  • commands 是类型为 List<CommandWithParties<CommandData>> 的 transaction 的 commands 和相关的签名者
  • attachments 是类型为 List<Attachment> 的 transaction 的 attachments
  • notary 是 transaction 的 notary。这个必须要同所有的 inputs 拥有相同的 notary
  • timeWindow 定义了一笔交易在什么样的时间窗(timewindow)内才会被公正(notarised)

LedgerTransaction 暴漏了很多 utility 方法来访问交易的内容:

  • inputStatesStateAndRef 列表中获得 input ContractState
  • getInput/getOutput/getCommand/getAttachment 通过索引(index)来获得某个组件
  • getAttachment 通过 ID 获得一个附件
  • inputsOfType/inRefsOfType/outputsOfType/outRefsOfType/commandsOfType 基于他们的类型获得相关组件
  • filterInputs/filterInRefs/filterOutputs/filterOutRefs/filterCommands 基于一个条件获得相关组件
  • findInput/findInRef/findOutput/findOutRef/findCommand 获得满足一定条件的单一组件,或者当有多个满足条件的组件的时候抛出异常

requireThat

verify 能够针对每一个约束手动地抛出异常:

override fun verify(tx: LedgerTransaction) {if (tx.inputs.size > 0)throw IllegalArgumentException("No inputs should be consumed when issuing an X.")if (tx.outputs.size != 1)throw IllegalArgumentException("Only one output state should be created.")
}

但是这个定义有些繁琐。我们可以使用 requireThat 来定义一系列的约束:

requireThat {"No inputs should be consumed when issuing an X." using (tx.inputs.isEmpty())"Only one output state should be created." using (tx.outputs.size == 1)val out = tx.outputs.single() as XState"The sender and the recipient cannot be the same entity." using (out.sender != out.recipient)"All of the participants must be signers." using (command.signers.containsAll(out.participants))"The X's value must be non-negative." using (out.x.value > 0)
}

对于 requireThat 中的每一个 <String, Boolean> 对来说,如果 boolean 条件返回的是 false,一个 IllegalArgumentException 会被抛出,包含对应的错误信息。所以这个错误会造成 transaction 被拒绝。

Commands

LedgerTransaction 包含了作为 CommandWithParties 实例列表的 commands。CommandWithParties 将一个 CommandData 和一个所需的签名者列表匹配起来:

/** A [Command] where the signing parties have been looked up if they have a well known/recognised institutional key. */
@CordaSerializable
data class CommandWithParties<out T : CommandData>(val signers: List<PublicKey>,/** If any public keys were recognised, the looked up institutions are available here */val signingParties: List<Party>,val value: T
)

其中:

  • signers 是每个签名者的 PublicKey 的一个列表
  • signingParties 签名者 identities 的列表,如果知道的话
  • value 是被签名的对象(在这里指的是这个 command)

使用 commands 来处理 verify 分支

总的来说,我们希望基于交易的 commands 来定义不同的约束条件。比如我们想要为一个现金发行的 transaction 和 一个现金交换的 transaction 定义不同的合约。

我们可以通过提取这个 command 并在 verify 里使用标准的分支逻辑来实现这个功能。这里我们提取了交易中的类型为 XContract.Commands 的单独的 command,并且相应地对 verify 进行了分支逻辑判断:

class XContract : Contract {interface Commands : CommandData {class Issue : TypeOnlyCommandData(), Commandsclass Transfer : TypeOnlyCommandData(), Commands}override fun verify(tx: LedgerTransaction) {val command = tx.findCommand<Commands> { true }when (command) {is Commands.Issue -> {// Issuance verification logic.}is Commands.Transfer -> {// Transfer verification logic.}}}
}

Legal prose

一个 Contract 类可以使用 @LegalProseReference 的 annotation。这个 annotation 能够将这个 contract code 同以法律条款的形式定义的文档关联起来,这个文档中定义的是跟 verify 里所定义的约束内容相同的内容。这个并不是必须的,但是当出现意见不统一的情况下,法律条款文件效力会优先于软件中的实现。

@LegalProseReference 仅仅有一个 uri 的输入参数,作为同 contract code 相关联的法律条款文档的标识:

@LegalProseReference(uri = "foo.bar.com/my-legal-doc.html")
class MyContract : Contract {override fun verify(tx: LedgerTransaction) {// Contract logic.}
}

Corda API:Contracts相关推荐

  1. node.js入门 - 9.api:http

    node一个重要任务是用来创建web服务,接下来我们就学习与此相关的一个重要的api -- http.我们使用http.createServer()创建一个http服务的实例,用来处理来自客户的请求. ...

  2. Netflix Play API:我们为什么构建了一个演进式架构?

    在QCon SF大会上,Suudhan Rangarajan做了题为"Netflix Play API:我们为什么构建了一个演进式架构"的演讲.他演讲的要点包括:具有单一标识/职责 ...

  3. CV之API:利用Face++的人体识别接口,实现摄像头实时手势识别

    CV之API:利用Face++的人体识别接口,实现摄像头实时手势识别 目录 测试图片 实现代码(部分) 测试图片 实现代码(部分) #利用Face++的人体识别接口,实现摄像头实时手势识别 impor ...

  4. TF学习——TF之API:TensorFlow的高级机器学习API—tf.contrib.learn的简介、使用方法、案例应用之详细攻略

    TF学习--TF之API:TensorFlow的高级机器学习API-tf.contrib.learn的简介.使用方法.案例应用之详细攻略 目录 tf.contrib.learn的简介 tf.contr ...

  5. ML之API:国内外各大人工智能平台(百度云/华为云/阿里云/Face++等)及其API的简介、使用方法之详细攻略

    ML之API:国内外各大人工智能平台(百度云/华为云/阿里云/Face++等)及其API的简介.使用方法之详细攻略 目录 一.百度云api 1.api之CV 二.旷视科技(face++)api 1.a ...

  6. OpenCV 高级API:TextDetectionModel和TextRecognitionModel

    高级API:TextDetectionModel和TextRecognitionModel TextDetectionModel和TextRecognitionModel 介绍 预训练模型 测试图像 ...

  7. api如何使用_记录API:技术作家和工程师指南

    在这门有关编写REST API文档的课程中,我不只是在谈论抽象概念,而是通过直接的动手方法将REST API关联起来.首先,您将通过使用简单的天气API在站点上放置天气预报来了解API文档. 使用AP ...

  8. WEB API:语音识别

    2019独角兽企业重金招聘Python工程师标准>>> x-webkit-speech 语音输入功能: http://www.iinterest.net/2012/01/07/x-w ...

  9. Google API:如何访问Google Analytics(分析)数据?

    在深入研究Google Analytics(分析)API之前,了解一些Google Analytics(分析)术语及其关系总是很有用的. Google帐户:要访问Google Analytics(分析 ...

最新文章

  1. sharepoint 备份还原
  2. Linux系统文件安全与权限
  3. 6个趣味项目,带你看看普通开发者如何玩转AI
  4. 基于stm32f107 stm32cube 和 LWIP 协议实现 udp 组播通信
  5. JavaScript+HTML设置视频预览图
  6. 实习二 分组密码加密_分组密码加密模式
  7. 盘点:最值得托付终身的星座
  8. 介绍MFSideMenu左右滑动控件的使用
  9. Mybatis源码阅读(二):动态节点解析2.2 —— SqlSourceBuilder与三种SqlSource
  10. 小甲鱼Python第二十二讲课后习题
  11. 【教程】Microsoft Wi-Fi Direct Virtual关闭方法
  12. HTML5编写船上航行,单体半滑行穿浪船船型与静水航行性能
  13. 万字长文!Go 后台项目架构思考与重构
  14. apache http server 停止工作_Tomcat9配置HTTP/2
  15. 日志服务(原SLS)新功能发布(5)--使用Logstash接入数据
  16. php svn更改密码,svn 开启修改备注
  17. vue+nodejs+element 实现drawio绘图效果
  18. mysql msi失败_MySQL .msi 安装失败改用.zip安装步骤
  19. 基于matlab的图像锐化,基于Matlab的图像锐化的研究
  20. Buzzsumo大型教程(内容营销+外链outreach必备)营销神器

热门文章

  1. Java里的键盘输入Scanner
  2. 多台CentOS服务器时间同步(NTP时间同步)
  3. <Python>PyQt5+OpenCv+Dlib人脸合成程序
  4. SQL判断一个事件段 是否在数据库中与其他时间段有重叠 判断时间重叠
  5. Android最新相机(Camera)拍照、拍视频全面总结
  6. c语言 孪生素数
  7. 像素位移_磁共振伪影知多少——化学位移伪影
  8. OLE方式保存Excel文件
  9. 多伦多大学utm计算机科学,2020年加拿大留学各大学学费一览(最新)
  10. CoInitializeEx 与CoInitialize的区别