mirror of
https://github.com/corda/corda.git
synced 2025-06-01 23:20:54 +00:00
Merge branch 'master' into dynamic-loading
This commit is contained in:
commit
800151b774
2
.gitignore
vendored
2
.gitignore
vendored
@ -22,6 +22,8 @@ lib/dokka.jar
|
|||||||
buyer
|
buyer
|
||||||
seller
|
seller
|
||||||
rate-fix-demo-data
|
rate-fix-demo-data
|
||||||
|
nodeA
|
||||||
|
nodeB
|
||||||
|
|
||||||
### JetBrains template
|
### JetBrains template
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||||
|
@ -88,12 +88,32 @@ data class TransactionForVerification(val inStates: List<ContractState>,
|
|||||||
* Utilities for contract writers to incorporate into their logic.
|
* Utilities for contract writers to incorporate into their logic.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of related inputs and outputs that are connected by some common attributes. An InOutGroup is calculated
|
||||||
|
* using [groupStates] and is useful for handling cases where a transaction may contain similar but unrelated
|
||||||
|
* state evolutions, for example, a transaction that moves cash in two different currencies. The numbers must add
|
||||||
|
* up on both sides of the transaction, but the values must be summed independently per currency. Grouping can
|
||||||
|
* be used to simplify this logic.
|
||||||
|
*/
|
||||||
data class InOutGroup<T : ContractState>(val inputs: List<T>, val outputs: List<T>)
|
data class InOutGroup<T : ContractState>(val inputs: List<T>, val outputs: List<T>)
|
||||||
|
|
||||||
// A shortcut to make IDE auto-completion more intuitive for Java users.
|
/** Simply calls [commands.getTimestampBy] as a shortcut to make code completion more intuitive. */
|
||||||
fun getTimestampBy(timestampingAuthority: Party): TimestampCommand? = commands.getTimestampBy(timestampingAuthority)
|
fun getTimestampBy(timestampingAuthority: Party): TimestampCommand? = commands.getTimestampBy(timestampingAuthority)
|
||||||
|
|
||||||
// For Java users.
|
/**
|
||||||
|
* Given a type and a function that returns a grouping key, associates inputs and outputs together so that they
|
||||||
|
* can be processed as one. The grouping key is any arbitrary object that can act as a map key (so must implement
|
||||||
|
* equals and hashCode).
|
||||||
|
*
|
||||||
|
* The purpose of this function is to simplify the writing of verification logic for transactions that may contain
|
||||||
|
* similar but unrelated state evolutions which need to be checked independently. Consider a transaction that
|
||||||
|
* simultaneously moves both dollars and euros (e.g. is an atomic FX trade). There may be multiple dollar inputs and
|
||||||
|
* multiple dollar outputs, depending on things like how fragmented the owners wallet is and whether various privacy
|
||||||
|
* techniques are in use. The quantity of dollars on the output side must sum to the same as on the input side, to
|
||||||
|
* ensure no money is being lost track of. This summation and checking must be repeated independently for each
|
||||||
|
* currency. To solve this, you would use groupStates with a type of Cash.State and a selector that returns the
|
||||||
|
* currency field: the resulting list can then be iterated over to perform the per-currency calculation.
|
||||||
|
*/
|
||||||
fun <T : ContractState> groupStates(ofType: Class<T>, selector: (T) -> Any): List<InOutGroup<T>> {
|
fun <T : ContractState> groupStates(ofType: Class<T>, selector: (T) -> Any): List<InOutGroup<T>> {
|
||||||
val inputs = inStates.filterIsInstance(ofType)
|
val inputs = inStates.filterIsInstance(ofType)
|
||||||
val outputs = outStates.filterIsInstance(ofType)
|
val outputs = outStates.filterIsInstance(ofType)
|
||||||
@ -105,7 +125,7 @@ data class TransactionForVerification(val inStates: List<ContractState>,
|
|||||||
return groupStatesInternal(inGroups, outGroups)
|
return groupStatesInternal(inGroups, outGroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Kotlin users: this version has nicer syntax and avoids reflection/object creation for the lambda.
|
/** See the documentation for the reflection-based version of [groupStates] */
|
||||||
inline fun <reified T : ContractState> groupStates(selector: (T) -> Any): List<InOutGroup<T>> {
|
inline fun <reified T : ContractState> groupStates(selector: (T) -> Any): List<InOutGroup<T>> {
|
||||||
val inputs = inStates.filterIsInstance<T>()
|
val inputs = inStates.filterIsInstance<T>()
|
||||||
val outputs = outStates.filterIsInstance<T>()
|
val outputs = outStates.filterIsInstance<T>()
|
||||||
|
@ -72,8 +72,6 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
|
|||||||
lateinit var api: APIServer
|
lateinit var api: APIServer
|
||||||
|
|
||||||
open fun start(): AbstractNode {
|
open fun start(): AbstractNode {
|
||||||
require(timestamperAddress == null || timestamperAddress.advertisedServices.contains(TimestamperService.Type))
|
|
||||||
{"Timestamper address must indicate a node that provides timestamping services"}
|
|
||||||
log.info("Node starting up ...")
|
log.info("Node starting up ...")
|
||||||
|
|
||||||
storage = initialiseStorageService(dir)
|
storage = initialiseStorageService(dir)
|
||||||
@ -98,6 +96,10 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
|
|||||||
// given the details, the timestamping node is somewhere else. Otherwise, we do our own timestamping.
|
// given the details, the timestamping node is somewhere else. Otherwise, we do our own timestamping.
|
||||||
val tsid = if (timestamperAddress != null) {
|
val tsid = if (timestamperAddress != null) {
|
||||||
inNodeTimestampingService = null
|
inNodeTimestampingService = null
|
||||||
|
require(TimestamperService.Type in timestamperAddress.advertisedServices) {
|
||||||
|
"Timestamper address must indicate a node that provides timestamping services, actually " +
|
||||||
|
"has ${timestamperAddress.advertisedServices}"
|
||||||
|
}
|
||||||
timestamperAddress
|
timestamperAddress
|
||||||
} else {
|
} else {
|
||||||
inNodeTimestampingService = NodeTimestamperService(net, storage.myLegalIdentity, storage.myLegalIdentityKey, platformClock)
|
inNodeTimestampingService = NodeTimestamperService(net, storage.myLegalIdentity, storage.myLegalIdentityKey, platformClock)
|
||||||
|
@ -11,10 +11,11 @@ import core.messaging.SingleMessageRecipient
|
|||||||
import core.node.Node
|
import core.node.Node
|
||||||
import core.node.NodeConfiguration
|
import core.node.NodeConfiguration
|
||||||
import core.node.NodeConfigurationFromConfig
|
import core.node.NodeConfigurationFromConfig
|
||||||
import core.node.services.ArtemisMessagingService
|
|
||||||
import core.node.NodeInfo
|
import core.node.NodeInfo
|
||||||
|
import core.node.services.ArtemisMessagingService
|
||||||
import core.node.services.NodeAttachmentService
|
import core.node.services.NodeAttachmentService
|
||||||
import core.node.services.NodeWalletService
|
import core.node.services.NodeWalletService
|
||||||
|
import core.node.services.TimestamperService
|
||||||
import core.protocols.ProtocolLogic
|
import core.protocols.ProtocolLogic
|
||||||
import core.serialization.deserialize
|
import core.serialization.deserialize
|
||||||
import core.utilities.ANSIProgressRenderer
|
import core.utilities.ANSIProgressRenderer
|
||||||
@ -87,7 +88,7 @@ fun main(args: Array<String>) {
|
|||||||
val addr = HostAndPort.fromString(options.valueOf(timestamperNetAddr)).withDefaultPort(Node.DEFAULT_PORT)
|
val addr = HostAndPort.fromString(options.valueOf(timestamperNetAddr)).withDefaultPort(Node.DEFAULT_PORT)
|
||||||
val path = Paths.get(options.valueOf(timestamperIdentityFile))
|
val path = Paths.get(options.valueOf(timestamperIdentityFile))
|
||||||
val party = Files.readAllBytes(path).deserialize<Party>(includeClassName = true)
|
val party = Files.readAllBytes(path).deserialize<Party>(includeClassName = true)
|
||||||
NodeInfo(ArtemisMessagingService.makeRecipient(addr), party)
|
NodeInfo(ArtemisMessagingService.makeRecipient(addr), party, advertisedServices = setOf(TimestamperService.Type))
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
val node = logElapsedTime("Node startup") { Node(dir, myNetAddr, config, timestamperId).start() }
|
val node = logElapsedTime("Node startup") { Node(dir, myNetAddr, config, timestamperId).start() }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user