mirror of
https://github.com/corda/corda.git
synced 2025-02-19 17:08:05 +00:00
Merge pull request #840 from corda/merges/may-14-15-21
Merges May 14 15:21
This commit is contained in:
commit
454899bc77
@ -9,7 +9,7 @@ omissions, and create a pull request, or email <james@r3.com>, if you wish to
|
|||||||
see changes to this list.
|
see changes to this list.
|
||||||
|
|
||||||
* acetheultimate
|
* acetheultimate
|
||||||
* Adrian Flethcehr (TD)
|
* Adrian Fletcher (TD)
|
||||||
* agoldvarg
|
* agoldvarg
|
||||||
* Alberto Arri (R3)
|
* Alberto Arri (R3)
|
||||||
* amiracam
|
* amiracam
|
||||||
@ -108,7 +108,7 @@ see changes to this list.
|
|||||||
* Lars Stage Thomsen (Danske Bank)
|
* Lars Stage Thomsen (Danske Bank)
|
||||||
* Lee Braine (Barclays)
|
* Lee Braine (Barclays)
|
||||||
* Lucas Salmen (Itau)
|
* Lucas Salmen (Itau)
|
||||||
* Maksymillian Pawlak (R3)
|
* Maksymilian Pawlak (R3)
|
||||||
* Marek Scocovsky (ABSA)
|
* Marek Scocovsky (ABSA)
|
||||||
* marekdapps
|
* marekdapps
|
||||||
* Mark Lauer (Westpac)
|
* Mark Lauer (Westpac)
|
||||||
@ -175,7 +175,8 @@ see changes to this list.
|
|||||||
* tomconte
|
* tomconte
|
||||||
* Tommy Lillehagen (R3)
|
* Tommy Lillehagen (R3)
|
||||||
* tomtau
|
* tomtau
|
||||||
* Tudor Malene (R3)
|
* Tudor Malene (R3)
|
||||||
|
* Tushar Singh Bora
|
||||||
* varunkm
|
* varunkm
|
||||||
* verymahler
|
* verymahler
|
||||||
* Viktor Kolomeyko (R3)
|
* Viktor Kolomeyko (R3)
|
||||||
|
@ -340,14 +340,14 @@ object JacksonSupport {
|
|||||||
mapper.wellKnownPartyFromX500Name(principal) ?: throw JsonParseException(parser, "Could not find a Party with name $principal")
|
mapper.wellKnownPartyFromX500Name(principal) ?: throw JsonParseException(parser, "Could not find a Party with name $principal")
|
||||||
} else {
|
} else {
|
||||||
val nameMatches = mapper.partiesFromName(parser.text)
|
val nameMatches = mapper.partiesFromName(parser.text)
|
||||||
if (nameMatches.isEmpty()) {
|
when {
|
||||||
val publicKey = parser.readValueAs<PublicKey>()
|
nameMatches.isEmpty() -> {
|
||||||
mapper.partyFromKey(publicKey)
|
val publicKey = parser.readValueAs<PublicKey>()
|
||||||
?: throw JsonParseException(parser, "Could not find a Party with key ${publicKey.toStringShort()}")
|
mapper.partyFromKey(publicKey)
|
||||||
} else if (nameMatches.size == 1) {
|
?: throw JsonParseException(parser, "Could not find a Party with key ${publicKey.toStringShort()}")
|
||||||
nameMatches.first()
|
}
|
||||||
} else {
|
nameMatches.size == 1 -> nameMatches.first()
|
||||||
throw JsonParseException(parser, "Ambiguous name match '${parser.text}': could be any of " +
|
else -> throw JsonParseException(parser, "Ambiguous name match '${parser.text}': could be any of " +
|
||||||
nameMatches.map { it.name }.joinToString(" ... or ... "))
|
nameMatches.map { it.name }.joinToString(" ... or ... "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ open class StringToMethodCallParser<in T : Any> @JvmOverloads constructor(
|
|||||||
val paramNames = methodParamNames[name]!!
|
val paramNames = methodParamNames[name]!!
|
||||||
val typeNames = args.parameters.map { it.type.simpleName }
|
val typeNames = args.parameters.map { it.type.simpleName }
|
||||||
val paramTypes = paramNames.zip(typeNames)
|
val paramTypes = paramNames.zip(typeNames)
|
||||||
paramTypes.map { "${it.first}: ${it.second}" }.joinToString(", ")
|
paramTypes.joinToString(", ") { "${it.first}: ${it.second}" }
|
||||||
}
|
}
|
||||||
Pair(name, argStr)
|
Pair(name, argStr)
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
@ -13,7 +13,6 @@ package net.corda.client.jackson
|
|||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import org.junit.Assert.assertArrayEquals
|
import org.junit.Assert.assertArrayEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.reflect.full.primaryConstructor
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class StringToMethodCallParserTest {
|
class StringToMethodCallParserTest {
|
||||||
|
@ -121,13 +121,13 @@ class NodeMonitorModelTest : IntegrationTest() {
|
|||||||
sequence(
|
sequence(
|
||||||
// TODO : Add test for remove when driver DSL support individual node shutdown.
|
// TODO : Add test for remove when driver DSL support individual node shutdown.
|
||||||
expect { output: NetworkMapCache.MapChange ->
|
expect { output: NetworkMapCache.MapChange ->
|
||||||
require(output.node.legalIdentities.any { it.name == ALICE_NAME }) { "Expecting : ${ALICE_NAME}, Actual : ${output.node.legalIdentities.map(Party::name)}" }
|
require(output.node.legalIdentities.any { it.name == ALICE_NAME }) { "Expecting : $ALICE_NAME, Actual : ${output.node.legalIdentities.map(Party::name)}" }
|
||||||
},
|
},
|
||||||
expect { output: NetworkMapCache.MapChange ->
|
expect { output: NetworkMapCache.MapChange ->
|
||||||
require(output.node.legalIdentities.any { it.name == BOB_NAME }) { "Expecting : ${BOB_NAME}, Actual : ${output.node.legalIdentities.map(Party::name)}" }
|
require(output.node.legalIdentities.any { it.name == BOB_NAME }) { "Expecting : $BOB_NAME, Actual : ${output.node.legalIdentities.map(Party::name)}" }
|
||||||
},
|
},
|
||||||
expect { output: NetworkMapCache.MapChange ->
|
expect { output: NetworkMapCache.MapChange ->
|
||||||
require(output.node.legalIdentities.any { it.name == CHARLIE_NAME }) { "Expecting : ${CHARLIE_NAME}, Actual : ${output.node.legalIdentities.map(Party::name)}" }
|
require(output.node.legalIdentities.any { it.name == CHARLIE_NAME }) { "Expecting : $CHARLIE_NAME, Actual : ${output.node.legalIdentities.map(Party::name)}" }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -39,24 +39,23 @@ class ContractStateModel {
|
|||||||
private val cashStatesDiff: Observable<Diff<Cash.State>> = contractStatesDiff.map {
|
private val cashStatesDiff: Observable<Diff<Cash.State>> = contractStatesDiff.map {
|
||||||
Diff(it.added.filterCashStateAndRefs(), it.removed.filterCashStateAndRefs())
|
Diff(it.added.filterCashStateAndRefs(), it.removed.filterCashStateAndRefs())
|
||||||
}
|
}
|
||||||
val cashStates: ObservableList<StateAndRef<Cash.State>> = cashStatesDiff.fold(FXCollections.observableArrayList()) { list: MutableList<StateAndRef<Cash.State>>, statesDiff ->
|
val cashStates: ObservableList<StateAndRef<Cash.State>> = cashStatesDiff.fold(FXCollections.observableArrayList()) { list: MutableList<StateAndRef<Cash.State>>, (added, removed) ->
|
||||||
list.removeIf { it in statesDiff.removed }
|
list.removeIf { it in removed }
|
||||||
list.addAll(statesDiff.added)
|
list.addAll(added)
|
||||||
}.distinctBy { it.ref }
|
}.distinctBy { it.ref }
|
||||||
|
|
||||||
val cash = cashStates.map { it.state.data.amount }
|
val cash = cashStates.map { it.state.data.amount }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun Collection<StateAndRef<ContractState>>.filterCashStateAndRefs(): List<StateAndRef<Cash.State>> {
|
private fun Collection<StateAndRef<ContractState>>.filterCashStateAndRefs(): List<StateAndRef<Cash.State>> {
|
||||||
return this.map { stateAndRef ->
|
return this.mapNotNull { stateAndRef ->
|
||||||
if (stateAndRef.state.data is Cash.State) {
|
if (stateAndRef.state.data is Cash.State) {
|
||||||
// Kotlin doesn't unify here for some reason
|
// Kotlin doesn't unify here for some reason
|
||||||
uncheckedCast<StateAndRef<ContractState>, StateAndRef<Cash.State>>(stateAndRef)
|
uncheckedCast<StateAndRef<ContractState>, StateAndRef<Cash.State>>(stateAndRef)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}.filterNotNull()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,7 @@
|
|||||||
|
|
||||||
package net.corda.client.jfx.model
|
package net.corda.client.jfx.model
|
||||||
|
|
||||||
import javafx.beans.property.ObjectProperty
|
|
||||||
import javafx.beans.value.ObservableValue
|
|
||||||
import javafx.beans.value.WritableValue
|
|
||||||
import javafx.collections.ObservableList
|
|
||||||
import net.corda.core.internal.uncheckedCast
|
import net.corda.core.internal.uncheckedCast
|
||||||
import org.reactfx.EventSink
|
|
||||||
import org.reactfx.EventStream
|
|
||||||
import rx.Observable
|
|
||||||
import rx.Observer
|
|
||||||
import rx.subjects.Subject
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@ -84,7 +75,7 @@ object Models {
|
|||||||
|
|
||||||
fun <M : Any> initModel(klass: KClass<M>) = modelStore.getOrPut(klass) { klass.java.newInstance() }
|
fun <M : Any> initModel(klass: KClass<M>) = modelStore.getOrPut(klass) { klass.java.newInstance() }
|
||||||
fun <M : Any> get(klass: KClass<M>, origin: KClass<*>): M {
|
fun <M : Any> get(klass: KClass<M>, origin: KClass<*>): M {
|
||||||
dependencyGraph.getOrPut(origin) { mutableSetOf<KClass<*>>() }.add(klass)
|
dependencyGraph.getOrPut(origin) { mutableSetOf() }.add(klass)
|
||||||
val model = initModel(klass)
|
val model = initModel(klass)
|
||||||
if (model.javaClass != klass.java) {
|
if (model.javaClass != klass.java) {
|
||||||
throw IllegalStateException("Model stored as ${klass.qualifiedName} has type ${model.javaClass}")
|
throw IllegalStateException("Model stored as ${klass.qualifiedName} has type ${model.javaClass}")
|
||||||
|
@ -21,7 +21,6 @@ import org.reactfx.EventStream
|
|||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Observer
|
import rx.Observer
|
||||||
import rx.subjects.Subject
|
import rx.subjects.Subject
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
inline fun <reified M : Any, T> observable(noinline observableProperty: (M) -> Observable<T>) =
|
inline fun <reified M : Any, T> observable(noinline observableProperty: (M) -> Observable<T>) =
|
||||||
TrackedDelegate.ObservableDelegate(M::class, observableProperty)
|
TrackedDelegate.ObservableDelegate(M::class, observableProperty)
|
||||||
|
@ -32,7 +32,7 @@ class NetworkIdentityModel {
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(update is MapChange.Modified || update is MapChange.Added){
|
if (update is MapChange.Modified || update is MapChange.Added) {
|
||||||
list.addAll(update.node)
|
list.addAll(update.node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,8 +95,8 @@ class TransactionDataModel {
|
|||||||
private val transactions by observable(NodeMonitorModel::transactions)
|
private val transactions by observable(NodeMonitorModel::transactions)
|
||||||
private val collectedTransactions = transactions.recordInSequence().distinctBy { it.id }
|
private val collectedTransactions = transactions.recordInSequence().distinctBy { it.id }
|
||||||
private val vaultUpdates by observable(NodeMonitorModel::vaultUpdates)
|
private val vaultUpdates by observable(NodeMonitorModel::vaultUpdates)
|
||||||
private val stateMap = vaultUpdates.fold(FXCollections.observableHashMap<StateRef, StateAndRef<ContractState>>()) { map, update ->
|
private val stateMap = vaultUpdates.fold(FXCollections.observableHashMap<StateRef, StateAndRef<ContractState>>()) { map, (consumed, produced) ->
|
||||||
val states = update.consumed + update.produced
|
val states = consumed + produced
|
||||||
states.forEach { map[it.ref] = it }
|
states.forEach { map[it.ref] = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,21 +80,25 @@ class AggregatedList<A, E : Any, K : Any>(
|
|||||||
override fun sourceChanged(c: ListChangeListener.Change<out E>) {
|
override fun sourceChanged(c: ListChangeListener.Change<out E>) {
|
||||||
beginChange()
|
beginChange()
|
||||||
while (c.next()) {
|
while (c.next()) {
|
||||||
if (c.wasPermutated()) {
|
when {
|
||||||
// Permutation should not change aggregation
|
c.wasPermutated() -> {
|
||||||
} else if (c.wasUpdated()) {
|
// Permutation should not change aggregation
|
||||||
// Update should not change aggregation
|
|
||||||
} else {
|
|
||||||
for (removedSourceItem in c.removed) {
|
|
||||||
val removedPair = removeItem(removedSourceItem)
|
|
||||||
if (removedPair != null) {
|
|
||||||
nextRemove(removedPair.first, removedPair.second.value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (addedItem in c.addedSubList) {
|
c.wasUpdated() -> {
|
||||||
val insertIndex = addItem(addedItem)
|
// Update should not change aggregation
|
||||||
if (insertIndex != null) {
|
}
|
||||||
nextAdd(insertIndex, insertIndex + 1)
|
else -> {
|
||||||
|
for (removedSourceItem in c.removed) {
|
||||||
|
val removedPair = removeItem(removedSourceItem)
|
||||||
|
if (removedPair != null) {
|
||||||
|
nextRemove(removedPair.first, removedPair.second.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (addedItem in c.addedSubList) {
|
||||||
|
val insertIndex = addItem(addedItem)
|
||||||
|
if (insertIndex != null) {
|
||||||
|
nextAdd(insertIndex, insertIndex + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import javafx.collections.ObservableList
|
|||||||
import net.corda.client.jfx.model.ExchangeRate
|
import net.corda.client.jfx.model.ExchangeRate
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import org.fxmisc.easybind.EasyBind
|
import org.fxmisc.easybind.EasyBind
|
||||||
|
import org.fxmisc.easybind.monadic.MonadicBinding
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ import java.util.stream.Collectors
|
|||||||
* Utility bindings for the [Amount] type, similar in spirit to [Bindings]
|
* Utility bindings for the [Amount] type, similar in spirit to [Bindings]
|
||||||
*/
|
*/
|
||||||
object AmountBindings {
|
object AmountBindings {
|
||||||
fun <T : Any> sum(amounts: ObservableList<Amount<T>>, token: T) = EasyBind.map(
|
fun <T : Any> sum(amounts: ObservableList<Amount<T>>, token: T): MonadicBinding<Amount<T>> = EasyBind.map(
|
||||||
Bindings.createLongBinding({
|
Bindings.createLongBinding({
|
||||||
amounts.stream().collect(Collectors.summingLong {
|
amounts.stream().collect(Collectors.summingLong {
|
||||||
require(it.token == token)
|
require(it.token == token)
|
||||||
|
@ -31,35 +31,39 @@ class AssociatedList<K, out A, B>(
|
|||||||
init {
|
init {
|
||||||
sourceList.forEach {
|
sourceList.forEach {
|
||||||
val key = toKey(it)
|
val key = toKey(it)
|
||||||
backingMap.set(key, Pair(assemble(key, it), Unit))
|
backingMap[key] = Pair(assemble(key, it), Unit)
|
||||||
}
|
}
|
||||||
sourceList.addListener { change: ListChangeListener.Change<out A> ->
|
sourceList.addListener { change: ListChangeListener.Change<out A> ->
|
||||||
while (change.next()) {
|
while (change.next()) {
|
||||||
if (change.wasPermutated()) {
|
when {
|
||||||
} else if (change.wasUpdated()) {
|
change.wasPermutated() -> {
|
||||||
} else {
|
|
||||||
val removedSourceMap = change.removed.associateBy(toKey)
|
|
||||||
val addedSourceMap = change.addedSubList.associateBy(toKey)
|
|
||||||
val removedMap = HashMap<K, B>()
|
|
||||||
val addedMap = HashMap<K, B>()
|
|
||||||
removedSourceMap.forEach {
|
|
||||||
val removed = backingMap.remove(it.key)?.first
|
|
||||||
removed ?: throw IllegalStateException("Removed list does not associate")
|
|
||||||
removedMap.put(it.key, removed)
|
|
||||||
}
|
}
|
||||||
addedSourceMap.forEach {
|
change.wasUpdated() -> {
|
||||||
val oldValue = backingMap.get(it.key)
|
}
|
||||||
val newValue = if (oldValue == null) {
|
else -> {
|
||||||
assemble(it.key, it.value)
|
val removedSourceMap = change.removed.associateBy(toKey)
|
||||||
} else {
|
val addedSourceMap = change.addedSubList.associateBy(toKey)
|
||||||
throw IllegalStateException("Several elements associated with same key")
|
val removedMap = HashMap<K, B>()
|
||||||
|
val addedMap = HashMap<K, B>()
|
||||||
|
removedSourceMap.forEach {
|
||||||
|
val removed = backingMap.remove(it.key)?.first
|
||||||
|
removed ?: throw IllegalStateException("Removed list does not associate")
|
||||||
|
removedMap.put(it.key, removed)
|
||||||
|
}
|
||||||
|
addedSourceMap.forEach {
|
||||||
|
val oldValue = backingMap.get(it.key)
|
||||||
|
val newValue = if (oldValue == null) {
|
||||||
|
assemble(it.key, it.value)
|
||||||
|
} else {
|
||||||
|
throw IllegalStateException("Several elements associated with same key")
|
||||||
|
}
|
||||||
|
backingMap.put(it.key, Pair(newValue, Unit))
|
||||||
|
addedMap.put(it.key, newValue)
|
||||||
|
}
|
||||||
|
val keys = removedMap.keys + addedMap.keys
|
||||||
|
keys.forEach { key ->
|
||||||
|
fireChange(createMapChange(key, removedMap.get(key), addedMap.get(key)))
|
||||||
}
|
}
|
||||||
backingMap.put(it.key, Pair(newValue, Unit))
|
|
||||||
addedMap.put(it.key, newValue)
|
|
||||||
}
|
|
||||||
val keys = removedMap.keys + addedMap.keys
|
|
||||||
keys.forEach { key ->
|
|
||||||
fireChange(createMapChange(key, removedMap.get(key), addedMap.get(key)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,7 @@ class ChosenList<E>(
|
|||||||
|
|
||||||
private var currentList = chosenListObservable.value
|
private var currentList = chosenListObservable.value
|
||||||
|
|
||||||
private val listener = object : ListChangeListener<E> {
|
private val listener = ListChangeListener<E> { change -> fireChange(change) }
|
||||||
override fun onChanged(change: ListChangeListener.Change<out E>) = fireChange(change)
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
chosenListObservable.addListener { _: Observable -> rechoose() }
|
chosenListObservable.addListener { _: Observable -> rechoose() }
|
||||||
@ -49,7 +47,7 @@ class ChosenList<E>(
|
|||||||
endChange()
|
endChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun get(index: Int) = currentList.get(index)
|
override fun get(index: Int): E = currentList[index]
|
||||||
override val size: Int get() = currentList.size
|
override val size: Int get() = currentList.size
|
||||||
|
|
||||||
private fun rechoose() {
|
private fun rechoose() {
|
||||||
|
@ -62,10 +62,10 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startingOffsetOf(listIndex: Int): Int {
|
private fun startingOffsetOf(listIndex: Int): Int {
|
||||||
if (listIndex == 0) {
|
return if (listIndex == 0) {
|
||||||
return 0
|
0
|
||||||
} else {
|
} else {
|
||||||
return nestedIndexOffsets[listIndex - 1]
|
nestedIndexOffsets[listIndex - 1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,11 +84,11 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
// firstTouched is the result list index of the beginning of the permutation.
|
// firstTouched is the result list index of the beginning of the permutation.
|
||||||
val firstTouched = startingOffset + change.from
|
val firstTouched = startingOffset + change.from
|
||||||
// We first set the non-permuted indices.
|
// We first set the non-permuted indices.
|
||||||
for (i in 0..firstTouched - 1) {
|
for (i in 0 until firstTouched) {
|
||||||
permutation[i] = i
|
permutation[i] = i
|
||||||
}
|
}
|
||||||
// Then the permuted ones.
|
// Then the permuted ones.
|
||||||
for (i in firstTouched..startingOffset + change.to - 1) {
|
for (i in firstTouched until startingOffset + change.to) {
|
||||||
permutation[startingOffset + i] = change.getPermutation(i)
|
permutation[startingOffset + i] = change.getPermutation(i)
|
||||||
}
|
}
|
||||||
nextPermutation(firstTouched, startingOffset + change.to, permutation)
|
nextPermutation(firstTouched, startingOffset + change.to, permutation)
|
||||||
@ -97,7 +97,7 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
// by the startingOffsetOf the nested list.
|
// by the startingOffsetOf the nested list.
|
||||||
val listIndex = indexMap[wrapped]!!.first
|
val listIndex = indexMap[wrapped]!!.first
|
||||||
val startingOffset = startingOffsetOf(listIndex)
|
val startingOffset = startingOffsetOf(listIndex)
|
||||||
for (i in change.from..change.to - 1) {
|
for (i in change.from until change.to) {
|
||||||
nextUpdate(startingOffset + i)
|
nextUpdate(startingOffset + i)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -154,7 +154,7 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
val newSubNestedIndexOffsets = IntArray(change.to - change.from)
|
val newSubNestedIndexOffsets = IntArray(change.to - change.from)
|
||||||
val firstTouched = if (change.from == 0) 0 else nestedIndexOffsets[change.from - 1]
|
val firstTouched = if (change.from == 0) 0 else nestedIndexOffsets[change.from - 1]
|
||||||
var currentOffset = firstTouched
|
var currentOffset = firstTouched
|
||||||
for (i in 0..change.to - change.from - 1) {
|
for (i in 0 until change.to - change.from) {
|
||||||
currentOffset += source[change.from + i].size
|
currentOffset += source[change.from + i].size
|
||||||
newSubNestedIndexOffsets[i] = currentOffset
|
newSubNestedIndexOffsets[i] = currentOffset
|
||||||
}
|
}
|
||||||
@ -162,24 +162,24 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
val concatenatedPermutation = IntArray(newSubNestedIndexOffsets.last())
|
val concatenatedPermutation = IntArray(newSubNestedIndexOffsets.last())
|
||||||
// Set the non-permuted part
|
// Set the non-permuted part
|
||||||
var offset = 0
|
var offset = 0
|
||||||
for (i in 0..change.from - 1) {
|
for (i in 0 until change.from) {
|
||||||
val nestedList = source[i]
|
val nestedList = source[i]
|
||||||
for (j in offset..offset + nestedList.size - 1) {
|
for (j in offset until offset + nestedList.size) {
|
||||||
concatenatedPermutation[j] = j
|
concatenatedPermutation[j] = j
|
||||||
}
|
}
|
||||||
offset += nestedList.size
|
offset += nestedList.size
|
||||||
}
|
}
|
||||||
// Now the permuted part
|
// Now the permuted part
|
||||||
for (i in 0..newSubNestedIndexOffsets.size - 1) {
|
for (i in 0 until newSubNestedIndexOffsets.size) {
|
||||||
val startingOffset = startingOffsetOf(change.from + i)
|
val startingOffset = startingOffsetOf(change.from + i)
|
||||||
val permutedListIndex = change.getPermutation(change.from + i)
|
val permutedListIndex = change.getPermutation(change.from + i)
|
||||||
val permutedOffset = (if (permutedListIndex == 0) 0 else newSubNestedIndexOffsets[permutedListIndex - 1])
|
val permutedOffset = (if (permutedListIndex == 0) 0 else newSubNestedIndexOffsets[permutedListIndex - 1])
|
||||||
for (j in 0..source[permutedListIndex].size - 1) {
|
for (j in 0 until source[permutedListIndex].size) {
|
||||||
concatenatedPermutation[startingOffset + j] = permutedOffset + j
|
concatenatedPermutation[startingOffset + j] = permutedOffset + j
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Record permuted offsets
|
// Record permuted offsets
|
||||||
for (i in 0..newSubNestedIndexOffsets.size - 1) {
|
for (i in 0 until newSubNestedIndexOffsets.size) {
|
||||||
nestedIndexOffsets[change.from + i] = newSubNestedIndexOffsets[i]
|
nestedIndexOffsets[change.from + i] = newSubNestedIndexOffsets[i]
|
||||||
}
|
}
|
||||||
nextPermutation(firstTouched, newSubNestedIndexOffsets.last(), concatenatedPermutation)
|
nextPermutation(firstTouched, newSubNestedIndexOffsets.last(), concatenatedPermutation)
|
||||||
@ -248,7 +248,7 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
if (firstInvalidatedPosition < source.size) {
|
if (firstInvalidatedPosition < source.size) {
|
||||||
val firstInvalid = firstInvalidatedPosition
|
val firstInvalid = firstInvalidatedPosition
|
||||||
var offset = if (firstInvalid == 0) 0 else nestedIndexOffsets[firstInvalid - 1]
|
var offset = if (firstInvalid == 0) 0 else nestedIndexOffsets[firstInvalid - 1]
|
||||||
for (i in firstInvalid..source.size - 1) {
|
for (i in firstInvalid until source.size) {
|
||||||
offset += source[i].size
|
offset += source[i].size
|
||||||
if (i < nestedIndexOffsets.size) {
|
if (i < nestedIndexOffsets.size) {
|
||||||
nestedIndexOffsets[i] = offset
|
nestedIndexOffsets[i] = offset
|
||||||
@ -266,10 +266,10 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
override val size: Int
|
override val size: Int
|
||||||
get() {
|
get() {
|
||||||
recalculateOffsets()
|
recalculateOffsets()
|
||||||
if (nestedIndexOffsets.size > 0) {
|
return if (nestedIndexOffsets.size > 0) {
|
||||||
return nestedIndexOffsets.last()
|
nestedIndexOffsets.last()
|
||||||
} else {
|
} else {
|
||||||
return 0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,17 +283,17 @@ class ConcatenatedList<A>(sourceList: ObservableList<ObservableList<A>>) : Trans
|
|||||||
comparison = { offset -> compareValues(offset, index) }
|
comparison = { offset -> compareValues(offset, index) }
|
||||||
)
|
)
|
||||||
|
|
||||||
if (listIndex >= 0) {
|
return if (listIndex >= 0) {
|
||||||
var nonEmptyListIndex = listIndex + 1
|
var nonEmptyListIndex = listIndex + 1
|
||||||
while (source[nonEmptyListIndex].isEmpty()) {
|
while (source[nonEmptyListIndex].isEmpty()) {
|
||||||
nonEmptyListIndex++
|
nonEmptyListIndex++
|
||||||
}
|
}
|
||||||
return source[nonEmptyListIndex][0]
|
source[nonEmptyListIndex][0]
|
||||||
} else {
|
} else {
|
||||||
// The element is in the range of this list
|
// The element is in the range of this list
|
||||||
val rangeListIndex = -listIndex - 1
|
val rangeListIndex = -listIndex - 1
|
||||||
val subListOffset = index - startingOffsetOf(rangeListIndex)
|
val subListOffset = index - startingOffsetOf(rangeListIndex)
|
||||||
return source[rangeListIndex][subListOffset]
|
source[rangeListIndex][subListOffset]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class FlattenedList<A>(val sourceList: ObservableList<out ObservableValue<out A>
|
|||||||
val from = c.from
|
val from = c.from
|
||||||
val to = c.to
|
val to = c.to
|
||||||
val permutation = IntArray(to, { c.getPermutation(it) })
|
val permutation = IntArray(to, { c.getPermutation(it) })
|
||||||
indexMap.replaceAll { _, pair -> Pair(permutation[pair.first], pair.second) }
|
indexMap.replaceAll { _, (first, second) -> Pair(permutation[first], second) }
|
||||||
nextPermutation(from, to, permutation)
|
nextPermutation(from, to, permutation)
|
||||||
} else if (c.wasUpdated()) {
|
} else if (c.wasUpdated()) {
|
||||||
throw UnsupportedOperationException("FlattenedList doesn't support Update changes")
|
throw UnsupportedOperationException("FlattenedList doesn't support Update changes")
|
||||||
@ -119,7 +119,7 @@ class FlattenedList<A>(val sourceList: ObservableList<out ObservableValue<out A>
|
|||||||
assert(sourceList.size == indexMap.size)
|
assert(sourceList.size == indexMap.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun get(index: Int) = sourceList.get(index).value
|
override fun get(index: Int): A = sourceList[index].value
|
||||||
|
|
||||||
override fun getSourceIndex(index: Int) = index
|
override fun getSourceIndex(index: Int) = index
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ class LeftOuterJoinedMap<K : Any, A, B, C>(
|
|||||||
) : ReadOnlyBackedObservableMapBase<K, C, SimpleObjectProperty<B?>>() {
|
) : ReadOnlyBackedObservableMapBase<K, C, SimpleObjectProperty<B?>>() {
|
||||||
init {
|
init {
|
||||||
leftTable.forEach { entry ->
|
leftTable.forEach { entry ->
|
||||||
val rightValueProperty = SimpleObjectProperty(rightTable.get(entry.key))
|
val rightValueProperty = SimpleObjectProperty(rightTable[entry.key])
|
||||||
backingMap.set(entry.key, Pair(assemble(entry.key, entry.value, rightValueProperty), rightValueProperty))
|
backingMap[entry.key] = Pair(assemble(entry.key, entry.value, rightValueProperty), rightValueProperty)
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTable.addListener { change: MapChangeListener.Change<out K, out A> ->
|
leftTable.addListener { change: MapChangeListener.Change<out K, out A> ->
|
||||||
@ -39,10 +39,10 @@ class LeftOuterJoinedMap<K : Any, A, B, C>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (change.wasAdded()) {
|
if (change.wasAdded()) {
|
||||||
val rightValue = rightTable.get(change.key)
|
val rightValue = rightTable[change.key]
|
||||||
val rightValueProperty = SimpleObjectProperty(rightValue)
|
val rightValueProperty = SimpleObjectProperty(rightValue)
|
||||||
val newValue = assemble(change.key, change.valueAdded, rightValueProperty)
|
val newValue = assemble(change.key, change.valueAdded, rightValueProperty)
|
||||||
backingMap.set(change.key, Pair(newValue, rightValueProperty))
|
backingMap[change.key] = Pair(newValue, rightValueProperty)
|
||||||
addedValue = newValue
|
addedValue = newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,11 +50,11 @@ class LeftOuterJoinedMap<K : Any, A, B, C>(
|
|||||||
}
|
}
|
||||||
rightTable.addListener { change: MapChangeListener.Change<out K, out B> ->
|
rightTable.addListener { change: MapChangeListener.Change<out K, out B> ->
|
||||||
if (change.wasRemoved() && !change.wasAdded()) {
|
if (change.wasRemoved() && !change.wasAdded()) {
|
||||||
backingMap.get(change.key)?.second?.set(null)
|
backingMap[change.key]?.second?.set(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.wasAdded()) {
|
if (change.wasAdded()) {
|
||||||
backingMap.get(change.key)?.second?.set(change.valueAdded)
|
backingMap[change.key]?.second?.set(change.valueAdded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ import javafx.collections.ObservableList
|
|||||||
import javafx.collections.transformation.TransformationList
|
import javafx.collections.transformation.TransformationList
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a variant of [EasyBind.map] where the mapped list is backed, therefore the mapping function will only be run
|
* This is a variant of [EasyBind.map] where the mapped list is backed, therefore the mapping function will only be run
|
||||||
* when an element is inserted or updated.
|
* when an element is inserted or updated.
|
||||||
|
@ -40,7 +40,7 @@ private fun onError(th: Throwable) {
|
|||||||
*/
|
*/
|
||||||
fun <A, B> Observable<A>.foldToObservableValue(initial: B, folderFun: (A, B) -> B): ObservableValue<B> {
|
fun <A, B> Observable<A>.foldToObservableValue(initial: B, folderFun: (A, B) -> B): ObservableValue<B> {
|
||||||
val result = SimpleObjectProperty<B>(initial)
|
val result = SimpleObjectProperty<B>(initial)
|
||||||
subscribe ({
|
subscribe({
|
||||||
Platform.runLater {
|
Platform.runLater {
|
||||||
result.set(folderFun(it, result.get()))
|
result.set(folderFun(it, result.get()))
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,10 @@ fun <A, B> ObservableValue<out A>.map(function: (A) -> B): ObservableValue<B> =
|
|||||||
* re-run the function.
|
* re-run the function.
|
||||||
*/
|
*/
|
||||||
fun <A, B> ObservableList<out A>.map(cached: Boolean = true, function: (A) -> B): ObservableList<B> {
|
fun <A, B> ObservableList<out A>.map(cached: Boolean = true, function: (A) -> B): ObservableList<B> {
|
||||||
if (cached) {
|
return if (cached) {
|
||||||
return MappedList(this, function)
|
MappedList(this, function)
|
||||||
} else {
|
} else {
|
||||||
return EasyBind.map(this, function)
|
EasyBind.map(this, function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,11 +130,7 @@ fun <A> ObservableList<out A>.filter(predicate: ObservableValue<(A) -> Boolean>)
|
|||||||
*/
|
*/
|
||||||
fun <A> ObservableList<out A?>.filterNotNull(): ObservableList<A> {
|
fun <A> ObservableList<out A?>.filterNotNull(): ObservableList<A> {
|
||||||
//TODO This is a tactical work round for an issue with SAM conversion (https://youtrack.jetbrains.com/issue/ALL-1552) so that the M10 explorer works.
|
//TODO This is a tactical work round for an issue with SAM conversion (https://youtrack.jetbrains.com/issue/ALL-1552) so that the M10 explorer works.
|
||||||
return uncheckedCast(uncheckedCast<Any, ObservableList<A?>>(this).filtered(object : Predicate<A?> {
|
return uncheckedCast(uncheckedCast<Any, ObservableList<A?>>(this).filtered { t -> t != null })
|
||||||
override fun test(t: A?): Boolean {
|
|
||||||
return t != null
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -257,8 +253,8 @@ fun <A : Any, B : Any, C, K : Any> ObservableList<A>.leftOuterJoin(
|
|||||||
assemble: (A, ObservableList<B>) -> C
|
assemble: (A, ObservableList<B>) -> C
|
||||||
): ObservableList<C> {
|
): ObservableList<C> {
|
||||||
val joinedMap = leftOuterJoin(rightTable, leftToJoinKey, rightToJoinKey)
|
val joinedMap = leftOuterJoin(rightTable, leftToJoinKey, rightToJoinKey)
|
||||||
return joinedMap.getObservableValues().map { pair ->
|
return joinedMap.getObservableValues().map { (first, second) ->
|
||||||
pair.first.map { assemble(it, pair.second) }
|
first.map { assemble(it, second) }
|
||||||
}.concatenate()
|
}.concatenate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,11 +277,9 @@ fun <A : Any, B : Any, K : Any> ObservableList<A>.leftOuterJoin(
|
|||||||
): ObservableMap<K, Pair<ObservableList<A>, ObservableList<B>>> {
|
): ObservableMap<K, Pair<ObservableList<A>, ObservableList<B>>> {
|
||||||
val leftTableMap = associateByAggregation(leftToJoinKey)
|
val leftTableMap = associateByAggregation(leftToJoinKey)
|
||||||
val rightTableMap = rightTable.associateByAggregation(rightToJoinKey)
|
val rightTableMap = rightTable.associateByAggregation(rightToJoinKey)
|
||||||
val joinedMap: ObservableMap<K, Pair<ObservableList<A>, ObservableList<B>>> =
|
return LeftOuterJoinedMap(leftTableMap, rightTableMap) { _, left, rightValue ->
|
||||||
LeftOuterJoinedMap(leftTableMap, rightTableMap) { _, left, rightValue ->
|
Pair(left, ChosenList(rightValue.map { it ?: FXCollections.emptyObservableList() }, "ChosenList from leftOuterJoin"))
|
||||||
Pair(left, ChosenList(rightValue.map { it ?: FXCollections.emptyObservableList() }, "ChosenList from leftOuterJoin"))
|
}
|
||||||
}
|
|
||||||
return joinedMap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <A> ObservableList<A>.getValueAt(index: Int): ObservableValue<A?> {
|
fun <A> ObservableList<A>.getValueAt(index: Int): ObservableValue<A?> {
|
||||||
|
@ -56,7 +56,7 @@ open class ReadOnlyBackedObservableMapBase<K, A, B> : ObservableMap<K, A> {
|
|||||||
|
|
||||||
override fun containsValue(value: A) = backingMap.any { it.value.first == value }
|
override fun containsValue(value: A) = backingMap.any { it.value.first == value }
|
||||||
|
|
||||||
override fun get(key: K) = backingMap.get(key)?.first
|
override fun get(key: K) = backingMap[key]?.first
|
||||||
|
|
||||||
override fun isEmpty() = backingMap.isEmpty()
|
override fun isEmpty() = backingMap.isEmpty()
|
||||||
|
|
||||||
|
@ -43,14 +43,14 @@ class ReplayedList<A>(sourceList: ObservableList<A>) : TransformationList<A, A>(
|
|||||||
}
|
}
|
||||||
nextPermutation(from, to, permutation)
|
nextPermutation(from, to, permutation)
|
||||||
} else if (c.wasUpdated()) {
|
} else if (c.wasUpdated()) {
|
||||||
for (i in c.from..c.to - 1) {
|
for (i in c.from until c.to) {
|
||||||
replayedList[i] = c.list[i]
|
replayedList[i] = c.list[i]
|
||||||
nextUpdate(i)
|
nextUpdate(i)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (c.wasRemoved()) {
|
if (c.wasRemoved()) {
|
||||||
val removePosition = c.from
|
val removePosition = c.from
|
||||||
for (i in 0..c.removedSize - 1) {
|
for (i in 0 until c.removedSize) {
|
||||||
replayedList.removeAt(removePosition)
|
replayedList.removeAt(removePosition)
|
||||||
}
|
}
|
||||||
nextRemove(c.from, c.removed)
|
nextRemove(c.from, c.removed)
|
||||||
@ -58,7 +58,7 @@ class ReplayedList<A>(sourceList: ObservableList<A>) : TransformationList<A, A>(
|
|||||||
if (c.wasAdded()) {
|
if (c.wasAdded()) {
|
||||||
val addStart = c.from
|
val addStart = c.from
|
||||||
val addEnd = c.to
|
val addEnd = c.to
|
||||||
for (i in addStart..addEnd - 1) {
|
for (i in addStart until addEnd) {
|
||||||
replayedList.add(i, c.list[i])
|
replayedList.add(i, c.list[i])
|
||||||
}
|
}
|
||||||
nextAdd(addStart, addEnd)
|
nextAdd(addStart, addEnd)
|
||||||
|
@ -29,9 +29,10 @@ class ExchangeRateModelTest {
|
|||||||
|
|
||||||
private fun assertEquals(one: Amount<Currency>, another: Amount<Currency>) {
|
private fun assertEquals(one: Amount<Currency>, another: Amount<Currency>) {
|
||||||
assertEquals(one.token, another.token)
|
assertEquals(one.token, another.token)
|
||||||
assertTrue("$one != $another", {(one.toDecimal() - another.toDecimal()).abs() < BigDecimal(0.01) })
|
assertTrue("$one != $another", { (one.toDecimal() - another.toDecimal()).abs() < BigDecimal(0.01) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `perform fx testing`() {
|
fun `perform fx testing`() {
|
||||||
val tenSwissies = Amount(10, BigDecimal.ONE, CHF)
|
val tenSwissies = Amount(10, BigDecimal.ONE, CHF)
|
||||||
|
@ -19,9 +19,9 @@ import kotlin.test.fail
|
|||||||
|
|
||||||
class AggregatedListTest {
|
class AggregatedListTest {
|
||||||
|
|
||||||
lateinit var sourceList: ObservableList<Int>
|
private lateinit var sourceList: ObservableList<Int>
|
||||||
lateinit var aggregatedList: ObservableList<Pair<Int, ObservableList<Int>>>
|
private lateinit var aggregatedList: ObservableList<Pair<Int, ObservableList<Int>>>
|
||||||
lateinit var replayedList: ObservableList<Pair<Int, ObservableList<Int>>>
|
private lateinit var replayedList: ObservableList<Pair<Int, ObservableList<Int>>>
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
|
@ -34,14 +34,13 @@ class ConcatenatedListTest {
|
|||||||
fun <A> ConcatenatedList<A>.checkInvariants() {
|
fun <A> ConcatenatedList<A>.checkInvariants() {
|
||||||
assertEquals(nestedIndexOffsets.size, source.size)
|
assertEquals(nestedIndexOffsets.size, source.size)
|
||||||
var currentOffset = 0
|
var currentOffset = 0
|
||||||
for (i in 0..source.size - 1) {
|
for (i in 0 until source.size) {
|
||||||
currentOffset += source[i].size
|
currentOffset += source[i].size
|
||||||
assertEquals(nestedIndexOffsets[i], currentOffset)
|
assertEquals(nestedIndexOffsets[i], currentOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(indexMap.size, source.size)
|
assertEquals(indexMap.size, source.size)
|
||||||
for (entry in indexMap) {
|
for ((wrapped, pair) in indexMap) {
|
||||||
val (wrapped, pair) = entry
|
|
||||||
val index = pair.first
|
val index = pair.first
|
||||||
val foundListIndices = ArrayList<Int>()
|
val foundListIndices = ArrayList<Int>()
|
||||||
source.forEachIndexed { i, list ->
|
source.forEachIndexed { i, list ->
|
||||||
@ -134,11 +133,7 @@ class ConcatenatedListTest {
|
|||||||
assertEquals(replayedList[2], "b")
|
assertEquals(replayedList[2], "b")
|
||||||
assertEquals(replayedList[3], "c")
|
assertEquals(replayedList[3], "c")
|
||||||
|
|
||||||
sourceList.sortWith(object : Comparator<ObservableList<String>> {
|
sourceList.sortWith(Comparator<ObservableList<String>> { p0, p1 -> p0.size - p1.size })
|
||||||
override fun compare(p0: ObservableList<String>, p1: ObservableList<String>): Int {
|
|
||||||
return p0.size - p1.size
|
|
||||||
}
|
|
||||||
})
|
|
||||||
concatenatedList.checkInvariants()
|
concatenatedList.checkInvariants()
|
||||||
assertEquals(replayedList.size, 4)
|
assertEquals(replayedList.size, 4)
|
||||||
assertEquals(replayedList[0], "hello")
|
assertEquals(replayedList[0], "hello")
|
||||||
@ -147,11 +142,7 @@ class ConcatenatedListTest {
|
|||||||
assertEquals(replayedList[3], "b")
|
assertEquals(replayedList[3], "b")
|
||||||
|
|
||||||
sourceList.add(0, FXCollections.observableArrayList("d", "e", "f"))
|
sourceList.add(0, FXCollections.observableArrayList("d", "e", "f"))
|
||||||
sourceList.sortWith(object : Comparator<ObservableList<String>> {
|
sourceList.sortWith(Comparator<ObservableList<String>> { p0, p1 -> p0.size - p1.size })
|
||||||
override fun compare(p0: ObservableList<String>, p1: ObservableList<String>): Int {
|
|
||||||
return p0.size - p1.size
|
|
||||||
}
|
|
||||||
})
|
|
||||||
concatenatedList.checkInvariants()
|
concatenatedList.checkInvariants()
|
||||||
assertEquals(replayedList.size, 7)
|
assertEquals(replayedList.size, 7)
|
||||||
assertEquals(replayedList[0], "hello")
|
assertEquals(replayedList[0], "hello")
|
||||||
|
@ -44,7 +44,6 @@ class MappedListTest {
|
|||||||
assertEquals(replayedList[0], 7)
|
assertEquals(replayedList[0], 7)
|
||||||
assertEquals(replayedList[1], 5)
|
assertEquals(replayedList[1], 5)
|
||||||
assertEquals(replayedList[2], 3)
|
assertEquals(replayedList[2], 3)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -20,14 +20,14 @@ import kotlin.test.assertEquals
|
|||||||
class ReplayedMap<K, A>(sourceMap: ObservableMap<K, A>) : ReadOnlyBackedObservableMapBase<K, A, Unit>() {
|
class ReplayedMap<K, A>(sourceMap: ObservableMap<K, A>) : ReadOnlyBackedObservableMapBase<K, A, Unit>() {
|
||||||
init {
|
init {
|
||||||
sourceMap.forEach {
|
sourceMap.forEach {
|
||||||
backingMap.set(it.key, Pair(it.value, Unit))
|
backingMap[it.key] = Pair(it.value, Unit)
|
||||||
}
|
}
|
||||||
sourceMap.addListener { change: MapChangeListener.Change<out K, out A> ->
|
sourceMap.addListener { change: MapChangeListener.Change<out K, out A> ->
|
||||||
if (change.wasRemoved()) {
|
if (change.wasRemoved()) {
|
||||||
assertEquals(backingMap.remove(change.key)!!.first, change.valueRemoved)
|
assertEquals(backingMap.remove(change.key)!!.first, change.valueRemoved)
|
||||||
}
|
}
|
||||||
if (change.wasAdded()) {
|
if (change.wasAdded()) {
|
||||||
backingMap.set(change.key, Pair(change.valueAdded, Unit))
|
backingMap[change.key] = Pair(change.valueAdded, Unit)
|
||||||
}
|
}
|
||||||
fireChange(change)
|
fireChange(change)
|
||||||
}
|
}
|
||||||
|
@ -52,5 +52,5 @@ fun CordaRPCOps.drainAndShutdown(): Observable<Unit> {
|
|||||||
.doOnError { error ->
|
.doOnError { error ->
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
.doOnCompleted { shutdown() }.map { }
|
.doOnCompleted { shutdown() }.map { }
|
||||||
}
|
}
|
@ -11,10 +11,6 @@
|
|||||||
package net.corda.client.rpc.internal
|
package net.corda.client.rpc.internal
|
||||||
|
|
||||||
import co.paralleluniverse.common.util.SameThreadExecutor
|
import co.paralleluniverse.common.util.SameThreadExecutor
|
||||||
import com.esotericsoftware.kryo.Kryo
|
|
||||||
import com.esotericsoftware.kryo.Serializer
|
|
||||||
import com.esotericsoftware.kryo.io.Input
|
|
||||||
import com.esotericsoftware.kryo.io.Output
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache
|
import com.github.benmanes.caffeine.cache.Cache
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine
|
import com.github.benmanes.caffeine.cache.Caffeine
|
||||||
import com.github.benmanes.caffeine.cache.RemovalCause
|
import com.github.benmanes.caffeine.cache.RemovalCause
|
||||||
@ -44,18 +40,27 @@ import net.corda.nodeapi.internal.DeduplicationChecker
|
|||||||
import org.apache.activemq.artemis.api.core.ActiveMQException
|
import org.apache.activemq.artemis.api.core.ActiveMQException
|
||||||
import org.apache.activemq.artemis.api.core.RoutingType
|
import org.apache.activemq.artemis.api.core.RoutingType
|
||||||
import org.apache.activemq.artemis.api.core.SimpleString
|
import org.apache.activemq.artemis.api.core.SimpleString
|
||||||
import org.apache.activemq.artemis.api.core.client.*
|
|
||||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE
|
import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ClientConsumer
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ClientMessage
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ClientProducer
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ClientSession
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory
|
||||||
|
import org.apache.activemq.artemis.api.core.client.FailoverEventType
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ServerLocator
|
||||||
import rx.Notification
|
import rx.Notification
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.UnicastSubject
|
import rx.subjects.UnicastSubject
|
||||||
import java.lang.reflect.InvocationHandler
|
import java.lang.reflect.InvocationHandler
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.time.Instant
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import java.util.concurrent.ScheduledExecutorService
|
||||||
|
import java.util.concurrent.ScheduledFuture
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import kotlin.reflect.jvm.javaMethod
|
import kotlin.reflect.jvm.javaMethod
|
||||||
|
|
||||||
@ -162,7 +167,7 @@ class RPCClientProxyHandler(
|
|||||||
private val serializationContextWithObservableContext = RpcClientObservableSerializer.createContext(serializationContext, observableContext)
|
private val serializationContextWithObservableContext = RpcClientObservableSerializer.createContext(serializationContext, observableContext)
|
||||||
|
|
||||||
private fun createRpcObservableMap(): RpcObservableMap {
|
private fun createRpcObservableMap(): RpcObservableMap {
|
||||||
val onObservableRemove = RemovalListener<InvocationId, UnicastSubject<Notification<*>>> { key, value, cause ->
|
val onObservableRemove = RemovalListener<InvocationId, UnicastSubject<Notification<*>>> { key, _, cause ->
|
||||||
val observableId = key!!
|
val observableId = key!!
|
||||||
val rpcCallSite = callSiteMap?.remove(observableId)
|
val rpcCallSite = callSiteMap?.remove(observableId)
|
||||||
if (cause == RemovalCause.COLLECTED) {
|
if (cause == RemovalCause.COLLECTED) {
|
||||||
@ -454,7 +459,7 @@ class RPCClientProxyHandler(
|
|||||||
|
|
||||||
log.debug("Trying to connect using ${transport.params}")
|
log.debug("Trying to connect using ${transport.params}")
|
||||||
try {
|
try {
|
||||||
if (serverLocator != null && !serverLocator.isClosed) {
|
if (!serverLocator.isClosed) {
|
||||||
sessionFactory = serverLocator.createSessionFactory(transport)
|
sessionFactory = serverLocator.createSessionFactory(transport)
|
||||||
} else {
|
} else {
|
||||||
log.warn("Stopping reconnect attempts.")
|
log.warn("Stopping reconnect attempts.")
|
||||||
|
@ -55,7 +55,6 @@ class KryoClientSerializationScheme : AbstractKryoSerializationScheme() {
|
|||||||
},
|
},
|
||||||
if (classLoader != null) AMQP_P2P_CONTEXT.withClassLoader(classLoader) else AMQP_P2P_CONTEXT,
|
if (classLoader != null) AMQP_P2P_CONTEXT.withClassLoader(classLoader) else AMQP_P2P_CONTEXT,
|
||||||
rpcClientContext = if (classLoader != null) KRYO_RPC_CLIENT_CONTEXT.withClassLoader(classLoader) else KRYO_RPC_CLIENT_CONTEXT)
|
rpcClientContext = if (classLoader != null) KRYO_RPC_CLIENT_CONTEXT.withClassLoader(classLoader) else KRYO_RPC_CLIENT_CONTEXT)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -57,7 +57,7 @@ object RpcClientObservableSerializer : Serializer<Observable<*>>() {
|
|||||||
}.dematerialize()
|
}.dematerialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Input.readInvocationId() : Trace.InvocationId? {
|
private fun Input.readInvocationId(): Trace.InvocationId? {
|
||||||
|
|
||||||
val value = readString() ?: return null
|
val value = readString() ?: return null
|
||||||
val timestamp = readLong()
|
val timestamp = readLong()
|
||||||
|
@ -228,7 +228,7 @@ class StandaloneCordaRPClientTest {
|
|||||||
flowHandle.returnValue.get()
|
flowHandle.returnValue.get()
|
||||||
|
|
||||||
val balance = rpcProxy.getCashBalance(USD)
|
val balance = rpcProxy.getCashBalance(USD)
|
||||||
println("Balance: " + balance)
|
println("Balance: $balance")
|
||||||
assertEquals(629.DOLLARS, balance)
|
assertEquals(629.DOLLARS, balance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class RPCConcurrencyTests : AbstractRPCTest() {
|
|||||||
override fun newLatch(numberOfDowns: Int): Long {
|
override fun newLatch(numberOfDowns: Int): Long {
|
||||||
val id = random63BitValue()
|
val id = random63BitValue()
|
||||||
val latch = CountDownLatch(numberOfDowns)
|
val latch = CountDownLatch(numberOfDowns)
|
||||||
latches.put(id, latch)
|
latches[id] = latch
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class RPCFailureTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `unserializable`() = rpc {
|
fun unserializable() = rpc {
|
||||||
assertThatThrownBy { it.getUnserializable() }.isInstanceOf(KryoException::class.java)
|
assertThatThrownBy { it.getUnserializable() }.isInstanceOf(KryoException::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@ class RepeatingBytesInputStream(val bytesToRepeat: ByteArray, val numberOfBytes:
|
|||||||
private var bytesLeft = numberOfBytes
|
private var bytesLeft = numberOfBytes
|
||||||
override fun available() = bytesLeft
|
override fun available() = bytesLeft
|
||||||
override fun read(): Int {
|
override fun read(): Int {
|
||||||
if (bytesLeft == 0) {
|
return if (bytesLeft == 0) {
|
||||||
return -1
|
-1
|
||||||
} else {
|
} else {
|
||||||
bytesLeft--
|
bytesLeft--
|
||||||
return bytesToRepeat[(numberOfBytes - bytesLeft) % bytesToRepeat.size].toInt()
|
bytesToRepeat[(numberOfBytes - bytesLeft) % bytesToRepeat.size].toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ class SwapIdentitiesFlow(private val otherParty: Party,
|
|||||||
// TODO: for increased privacy, we should create one anonymous key per output state.
|
// TODO: for increased privacy, we should create one anonymous key per output state.
|
||||||
val identities = LinkedHashMap<Party, AnonymousParty>()
|
val identities = LinkedHashMap<Party, AnonymousParty>()
|
||||||
if (serviceHub.myInfo.isLegalIdentity(otherParty)) {
|
if (serviceHub.myInfo.isLegalIdentity(otherParty)) {
|
||||||
identities.put(otherParty, legalIdentityAnonymous.party.anonymise())
|
identities[otherParty] = legalIdentityAnonymous.party.anonymise()
|
||||||
} else {
|
} else {
|
||||||
val otherSession = initiateFlow(otherParty)
|
val otherSession = initiateFlow(otherParty)
|
||||||
val data = buildDataToSign(legalIdentityAnonymous)
|
val data = buildDataToSign(legalIdentityAnonymous)
|
||||||
|
@ -119,7 +119,7 @@ class IdentitySyncFlowTests {
|
|||||||
* Very lightweight wrapping flow to trigger the counterparty flow that receives the identities.
|
* Very lightweight wrapping flow to trigger the counterparty flow that receives the identities.
|
||||||
*/
|
*/
|
||||||
@InitiatingFlow
|
@InitiatingFlow
|
||||||
class Initiator(private val otherSide: Party, private val tx: WireTransaction): FlowLogic<Boolean>() {
|
class Initiator(private val otherSide: Party, private val tx: WireTransaction) : FlowLogic<Boolean>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): Boolean {
|
override fun call(): Boolean {
|
||||||
val session = initiateFlow(otherSide)
|
val session = initiateFlow(otherSide)
|
||||||
@ -130,7 +130,7 @@ class IdentitySyncFlowTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InitiatedBy(IdentitySyncFlowTests.Initiator::class)
|
@InitiatedBy(IdentitySyncFlowTests.Initiator::class)
|
||||||
class Receive(private val otherSideSession: FlowSession): FlowLogic<Unit>() {
|
class Receive(private val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() {
|
override fun call() {
|
||||||
subFlow(IdentitySyncFlow.Receive(otherSideSession))
|
subFlow(IdentitySyncFlow.Receive(otherSideSession))
|
||||||
|
@ -93,7 +93,7 @@ public class Base58 {
|
|||||||
* @throws AddressFormatException if the given string is not a valid base58 string
|
* @throws AddressFormatException if the given string is not a valid base58 string
|
||||||
*/
|
*/
|
||||||
public static byte[] decode(String input) throws AddressFormatException {
|
public static byte[] decode(String input) throws AddressFormatException {
|
||||||
if (input.length() == 0) {
|
if (input.isEmpty()) {
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
// Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits).
|
// Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits).
|
||||||
|
@ -20,7 +20,8 @@ public interface IdentifiableException {
|
|||||||
/**
|
/**
|
||||||
* @return the ID of the error, or null if the error doesn't have it set (yet).
|
* @return the ID of the error, or null if the error doesn't have it set (yet).
|
||||||
*/
|
*/
|
||||||
default @Nullable Long getErrorId() {
|
@Nullable
|
||||||
|
default Long getErrorId() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,10 @@ object CordaOID {
|
|||||||
/** Assigned to R3, see http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.4.1.50530&action=display */
|
/** Assigned to R3, see http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.4.1.50530&action=display */
|
||||||
const val R3_ROOT = "1.3.6.1.4.1.50530"
|
const val R3_ROOT = "1.3.6.1.4.1.50530"
|
||||||
/** OIDs issued for the Corda platform */
|
/** OIDs issued for the Corda platform */
|
||||||
const val CORDA_PLATFORM = R3_ROOT + ".1"
|
const val CORDA_PLATFORM = "$R3_ROOT.1"
|
||||||
/**
|
/**
|
||||||
* Identifier for the X.509 certificate extension specifying the Corda role. See
|
* Identifier for the X.509 certificate extension specifying the Corda role. See
|
||||||
* https://r3-cev.atlassian.net/wiki/spaces/AWG/pages/156860572/Certificate+identity+type+extension for details.
|
* https://r3-cev.atlassian.net/wiki/spaces/AWG/pages/156860572/Certificate+identity+type+extension for details.
|
||||||
*/
|
*/
|
||||||
const val X509_EXTENSION_CORDA_ROLE = CORDA_PLATFORM + ".1"
|
const val X509_EXTENSION_CORDA_ROLE = "$CORDA_PLATFORM.1"
|
||||||
}
|
}
|
@ -46,12 +46,12 @@ internal fun <V, W> firstOf(futures: Array<out CordaFuture<out V>>, log: Logger,
|
|||||||
val winnerChosen = AtomicBoolean()
|
val winnerChosen = AtomicBoolean()
|
||||||
futures.forEach {
|
futures.forEach {
|
||||||
it.then {
|
it.then {
|
||||||
if (winnerChosen.compareAndSet(false, true)) {
|
when {
|
||||||
resultFuture.capture { handler(it) }
|
winnerChosen.compareAndSet(false, true) -> resultFuture.capture { handler(it) }
|
||||||
} else if (it.isCancelled) {
|
it.isCancelled -> {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else {
|
}
|
||||||
it.match({}, { log.error(shortCircuitedTaskFailedMessage, it) })
|
else -> it.match({}, { log.error(shortCircuitedTaskFailedMessage, it) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@ data class Actor(val id: Id, val serviceId: AuthServiceId, val owningLegalIdenti
|
|||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class Id(val value: String)
|
data class Id(val value: String)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +37,7 @@ data class Trace(val invocationId: InvocationId, val sessionId: SessionId) {
|
|||||||
class InvocationId(value: String, timestamp: Instant) : Id<String>(value, TYPE, timestamp) {
|
class InvocationId(value: String, timestamp: Instant) : Id<String>(value, TYPE, timestamp) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TYPE = "Invocation"
|
private const val TYPE = "Invocation"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an invocation id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
* Creates an invocation id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
||||||
@ -54,7 +54,7 @@ data class Trace(val invocationId: InvocationId, val sessionId: SessionId) {
|
|||||||
class SessionId(value: String, timestamp: Instant) : Id<String>(value, TYPE, timestamp) {
|
class SessionId(value: String, timestamp: Instant) : Id<String>(value, TYPE, timestamp) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TYPE = "Session"
|
private const val TYPE = "Session"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a session id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
* Creates a session id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
||||||
|
@ -260,7 +260,7 @@ data class Amount<T : Any>(val quantity: Long, val displayTokenSize: BigDecimal,
|
|||||||
val residualTokens = quantity - (commonTokensPerPartition * partitions)
|
val residualTokens = quantity - (commonTokensPerPartition * partitions)
|
||||||
val splitAmount = Amount(commonTokensPerPartition, displayTokenSize, token)
|
val splitAmount = Amount(commonTokensPerPartition, displayTokenSize, token)
|
||||||
val splitAmountPlusOne = Amount(commonTokensPerPartition + 1L, displayTokenSize, token)
|
val splitAmountPlusOne = Amount(commonTokensPerPartition + 1L, displayTokenSize, token)
|
||||||
return (0..partitions - 1).map { if (it < residualTokens) splitAmountPlusOne else splitAmount }.toList()
|
return (0 until partitions).map { if (it < residualTokens) splitAmountPlusOne else splitAmount }.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,11 +20,11 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
* @property additionalContracts Additional contract names contained within the JAR.
|
* @property additionalContracts Additional contract names contained within the JAR.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
class ContractAttachment @JvmOverloads constructor (val attachment: Attachment, val contract: ContractClassName, val additionalContracts: Set<ContractClassName> = emptySet(), val uploader: String? = null) : Attachment by attachment {
|
class ContractAttachment @JvmOverloads constructor(val attachment: Attachment, val contract: ContractClassName, val additionalContracts: Set<ContractClassName> = emptySet(), val uploader: String? = null) : Attachment by attachment {
|
||||||
|
|
||||||
val allContracts: Set<ContractClassName> get() = additionalContracts + contract
|
val allContracts: Set<ContractClassName> get() = additionalContracts + contract
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "ContractAttachment(attachment=${attachment.id}, contracts='${allContracts}', uploader='${uploader}')"
|
return "ContractAttachment(attachment=${attachment.id}, contracts='$allContracts', uploader='$uploader')"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,7 +30,7 @@ import java.util.*
|
|||||||
object Requirements {
|
object Requirements {
|
||||||
/** Throws [IllegalArgumentException] if the given expression evaluates to false. */
|
/** Throws [IllegalArgumentException] if the given expression evaluates to false. */
|
||||||
@Suppress("NOTHING_TO_INLINE") // Inlining this takes it out of our committed ABI.
|
@Suppress("NOTHING_TO_INLINE") // Inlining this takes it out of our committed ABI.
|
||||||
infix inline fun String.using(expr: Boolean) {
|
inline infix fun String.using(expr: Boolean) {
|
||||||
if (!expr) throw IllegalArgumentException("Failed requirement: $this")
|
if (!expr) throw IllegalArgumentException("Failed requirement: $this")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ data class Command<T : CommandData>(val value: T, val signers: List<PublicKey>)
|
|||||||
constructor(data: T, key: PublicKey) : this(data, listOf(key))
|
constructor(data: T, key: PublicKey) : this(data, listOf(key))
|
||||||
|
|
||||||
private fun commandDataToString() = value.toString().let { if (it.contains("@")) it.replace('$', '.').split("@")[0] else it }
|
private fun commandDataToString() = value.toString().let { if (it.contains("@")) it.replace('$', '.').split("@")[0] else it }
|
||||||
override fun toString() = "${commandDataToString()} with pubkeys ${signers.map { it.toStringShort() }.joinToString()}"
|
override fun toString() = "${commandDataToString()} with pubkeys ${signers.joinToString { it.toStringShort() }}"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A common move command for contract states which can change owner. */
|
/** A common move command for contract states which can change owner. */
|
||||||
|
@ -52,7 +52,7 @@ sealed class TransactionVerificationException(val txId: SecureHash, message: Str
|
|||||||
* @property contractClass The fully qualified class name of the failing contract.
|
* @property contractClass The fully qualified class name of the failing contract.
|
||||||
*/
|
*/
|
||||||
class ContractRejection(txId: SecureHash, val contractClass: String, cause: Throwable) : TransactionVerificationException(txId, "Contract verification failed: ${cause.message}, contract: $contractClass", cause) {
|
class ContractRejection(txId: SecureHash, val contractClass: String, cause: Throwable) : TransactionVerificationException(txId, "Contract verification failed: ${cause.message}, contract: $contractClass", cause) {
|
||||||
constructor(txId: SecureHash, contract: Contract, cause: Throwable) : this(txId, contract.javaClass.name, cause)
|
constructor(txId: SecureHash, contract: Contract, cause: Throwable) : this(txId, contract.javaClass.name, cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,8 +118,10 @@ sealed class TransactionVerificationException(val txId: SecureHash, message: Str
|
|||||||
/** Whether the inputs or outputs list contains an encumbrance issue, see [TransactionMissingEncumbranceException]. */
|
/** Whether the inputs or outputs list contains an encumbrance issue, see [TransactionMissingEncumbranceException]. */
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
enum class Direction {
|
enum class Direction {
|
||||||
/** Issue in the inputs list */ INPUT,
|
/** Issue in the inputs list */
|
||||||
/** Issue in the outputs list */ OUTPUT
|
INPUT,
|
||||||
|
/** Issue in the outputs list */
|
||||||
|
OUTPUT
|
||||||
}
|
}
|
||||||
|
|
||||||
// We could revisit and throw this more appropriate type in a future release that uses targetVersion to
|
// We could revisit and throw this more appropriate type in a future release that uses targetVersion to
|
||||||
|
@ -43,7 +43,7 @@ interface Cordapp {
|
|||||||
val contractClassNames: List<String>
|
val contractClassNames: List<String>
|
||||||
val initiatedFlows: List<Class<out FlowLogic<*>>>
|
val initiatedFlows: List<Class<out FlowLogic<*>>>
|
||||||
val rpcFlows: List<Class<out FlowLogic<*>>>
|
val rpcFlows: List<Class<out FlowLogic<*>>>
|
||||||
val serviceFlows: List<Class<out FlowLogic<*>>>
|
val serviceFlows: List<Class<out FlowLogic<*>>>
|
||||||
val schedulableFlows: List<Class<out FlowLogic<*>>>
|
val schedulableFlows: List<Class<out FlowLogic<*>>>
|
||||||
val services: List<Class<out SerializeAsToken>>
|
val services: List<Class<out SerializeAsToken>>
|
||||||
val serializationWhitelists: List<SerializationWhitelist>
|
val serializationWhitelists: List<SerializationWhitelist>
|
||||||
|
@ -110,7 +110,7 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
|||||||
// We can't print the node details, because doing so involves serializing the node, which we can't
|
// We can't print the node details, because doing so involves serializing the node, which we can't
|
||||||
// do because of the cyclic graph.
|
// do because of the cyclic graph.
|
||||||
require(!curVisitedMap.contains(node)) { "Cycle detected for CompositeKey" }
|
require(!curVisitedMap.contains(node)) { "Cycle detected for CompositeKey" }
|
||||||
curVisitedMap.put(node, true)
|
curVisitedMap[node] = true
|
||||||
node.cycleDetection(curVisitedMap)
|
node.cycleDetection(curVisitedMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
|||||||
fun checkValidity() {
|
fun checkValidity() {
|
||||||
if (validated) return
|
if (validated) return
|
||||||
val visitedMap = IdentityHashMap<CompositeKey, Boolean>()
|
val visitedMap = IdentityHashMap<CompositeKey, Boolean>()
|
||||||
visitedMap.put(this, true)
|
visitedMap[this] = true
|
||||||
cycleDetection(visitedMap) // Graph cycle testing on the root node.
|
cycleDetection(visitedMap) // Graph cycle testing on the root node.
|
||||||
checkConstraints()
|
checkConstraints()
|
||||||
for ((node, _) in children) {
|
for ((node, _) in children) {
|
||||||
@ -281,15 +281,17 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
|||||||
fun build(threshold: Int? = null): PublicKey {
|
fun build(threshold: Int? = null): PublicKey {
|
||||||
require(threshold == null || threshold > 0)
|
require(threshold == null || threshold > 0)
|
||||||
val n = children.size
|
val n = children.size
|
||||||
return if (n > 1)
|
return when {
|
||||||
CompositeKey(threshold ?: children.map { (_, weight) -> weight }.sum(), children)
|
n > 1 -> CompositeKey(threshold ?: children.map { (_, weight) -> weight }.sum(), children)
|
||||||
else if (n == 1) {
|
n == 1 -> {
|
||||||
require(threshold == null || threshold == children.first().weight)
|
require(threshold == null || threshold == children.first().weight)
|
||||||
{ "Trying to build invalid CompositeKey, threshold value different than weight of single child node." }
|
{ "Trying to build invalid CompositeKey, threshold value different than weight of single child node." }
|
||||||
// Returning the only child node which is [PublicKey] itself. We need to avoid single-key [CompositeKey] instances,
|
// Returning the only child node which is [PublicKey] itself. We need to avoid single-key [CompositeKey] instances,
|
||||||
// as there are scenarios where developers expected the underlying key and its composite versions to be equivalent.
|
// as there are scenarios where developers expected the underlying key and its composite versions to be equivalent.
|
||||||
children.first().node
|
children.first().node
|
||||||
} else throw IllegalStateException("Trying to build CompositeKey without child nodes.")
|
}
|
||||||
|
else -> throw IllegalStateException("Trying to build CompositeKey without child nodes.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,8 +58,8 @@ sealed class MerkleTree {
|
|||||||
* @return Tree root.
|
* @return Tree root.
|
||||||
*/
|
*/
|
||||||
private tailrec fun buildMerkleTree(lastNodesList: List<MerkleTree>): MerkleTree {
|
private tailrec fun buildMerkleTree(lastNodesList: List<MerkleTree>): MerkleTree {
|
||||||
if (lastNodesList.size == 1) {
|
return if (lastNodesList.size == 1) {
|
||||||
return lastNodesList[0] // Root reached.
|
lastNodesList[0] // Root reached.
|
||||||
} else {
|
} else {
|
||||||
val newLevelHashes: MutableList<MerkleTree> = ArrayList()
|
val newLevelHashes: MutableList<MerkleTree> = ArrayList()
|
||||||
val n = lastNodesList.size
|
val n = lastNodesList.size
|
||||||
@ -71,7 +71,7 @@ sealed class MerkleTree {
|
|||||||
val combined = Node(newHash, left, right)
|
val combined = Node(newHash, left, right)
|
||||||
newLevelHashes.add(combined)
|
newLevelHashes.add(combined)
|
||||||
}
|
}
|
||||||
return buildMerkleTree(newLevelHashes)
|
buildMerkleTree(newLevelHashes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,5 +28,4 @@ object NullKeys {
|
|||||||
|
|
||||||
/** A signature with a key and value of zero. Useful when you want a signature object that you know won't ever be used. */
|
/** A signature with a key and value of zero. Useful when you want a signature object that you know won't ever be used. */
|
||||||
val NULL_SIGNATURE = TransactionSignature(ByteArray(32), NullPublicKey, SignatureMetadata(1, -1))
|
val NULL_SIGNATURE = TransactionSignature(ByteArray(32), NullPublicKey, SignatureMetadata(1, -1))
|
||||||
|
|
||||||
}
|
}
|
@ -46,7 +46,7 @@ open class SignedData<T : Any>(val raw: SerializedBytes<T>, val sig: DigitalSign
|
|||||||
* @throws IllegalArgumentException if the data is invalid.
|
* @throws IllegalArgumentException if the data is invalid.
|
||||||
*/
|
*/
|
||||||
@Throws(IllegalArgumentException::class)
|
@Throws(IllegalArgumentException::class)
|
||||||
open protected fun verifyData(data: T) {
|
protected open fun verifyData(data: T) {
|
||||||
// By default we accept anything
|
// By default we accept anything
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ abstract class AbstractStateReplacementFlow {
|
|||||||
val finalTx = stx + signatures
|
val finalTx = stx + signatures
|
||||||
serviceHub.recordTransactions(finalTx)
|
serviceHub.recordTransactions(finalTx)
|
||||||
|
|
||||||
return stx.resolveBaseTransaction(serviceHub).outRef<T>(0)
|
return stx.resolveBaseTransaction(serviceHub).outRef(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +88,7 @@ abstract class AbstractStateReplacementFlow {
|
|||||||
*
|
*
|
||||||
* @return the transaction
|
* @return the transaction
|
||||||
*/
|
*/
|
||||||
abstract protected fun assembleTx(): UpgradeTx
|
protected abstract fun assembleTx(): UpgradeTx
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiate sessions with parties we want signatures from.
|
* Initiate sessions with parties we want signatures from.
|
||||||
@ -186,7 +186,7 @@ abstract class AbstractStateReplacementFlow {
|
|||||||
* The proposal is returned if acceptable, otherwise a [StateReplacementException] is thrown.
|
* The proposal is returned if acceptable, otherwise a [StateReplacementException] is thrown.
|
||||||
*/
|
*/
|
||||||
@Throws(StateReplacementException::class)
|
@Throws(StateReplacementException::class)
|
||||||
abstract protected fun verifyProposal(stx: SignedTransaction, proposal: Proposal<T>)
|
protected abstract fun verifyProposal(stx: SignedTransaction, proposal: Proposal<T>)
|
||||||
|
|
||||||
private fun checkMySignatureRequired(stx: SignedTransaction) {
|
private fun checkMySignatureRequired(stx: SignedTransaction) {
|
||||||
// TODO: use keys from the keyManagementService instead
|
// TODO: use keys from the keyManagementService instead
|
||||||
|
@ -88,7 +88,8 @@ class CollectSignaturesFlow @JvmOverloads constructor(val partiallySignedTx: Sig
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suspendable override fun call(): SignedTransaction {
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
// Check the signatures which have already been provided and that the transaction is valid.
|
// Check the signatures which have already been provided and that the transaction is valid.
|
||||||
// Usually just the Initiator and possibly an oracle would have signed at this point.
|
// Usually just the Initiator and possibly an oracle would have signed at this point.
|
||||||
val myKeys: Iterable<PublicKey> = myOptionalKeys ?: listOf(ourIdentity.owningKey)
|
val myKeys: Iterable<PublicKey> = myOptionalKeys ?: listOf(ourIdentity.owningKey)
|
||||||
@ -216,7 +217,8 @@ abstract class SignTransactionFlow(val otherSideSession: FlowSession,
|
|||||||
fun tracker() = ProgressTracker(RECEIVING, VERIFYING, SIGNING)
|
fun tracker() = ProgressTracker(RECEIVING, VERIFYING, SIGNING)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suspendable override fun call(): SignedTransaction {
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
progressTracker.currentStep = RECEIVING
|
progressTracker.currentStep = RECEIVING
|
||||||
// Receive transaction and resolve dependencies, check sufficient signatures is disabled as we don't have all signatures.
|
// Receive transaction and resolve dependencies, check sufficient signatures is disabled as we don't have all signatures.
|
||||||
val stx = subFlow(ReceiveTransactionFlow(otherSideSession, checkSufficientSignatures = false))
|
val stx = subFlow(ReceiveTransactionFlow(otherSideSession, checkSufficientSignatures = false))
|
||||||
@ -253,12 +255,13 @@ abstract class SignTransactionFlow(val otherSideSession: FlowSession,
|
|||||||
return stx + mySignatures
|
return stx + mySignatures
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suspendable private fun checkSignatures(stx: SignedTransaction) {
|
@Suspendable
|
||||||
|
private fun checkSignatures(stx: SignedTransaction) {
|
||||||
// We set `ignoreUnrecognisedParties` to `true` in `groupPublicKeysByWellKnownParty`. This is because we don't
|
// We set `ignoreUnrecognisedParties` to `true` in `groupPublicKeysByWellKnownParty`. This is because we don't
|
||||||
// need to recognise all keys, but just the initiator's.
|
// need to recognise all keys, but just the initiator's.
|
||||||
val signingWellKnownIdentities = groupPublicKeysByWellKnownParty(serviceHub, stx.sigs.map(TransactionSignature::by), true)
|
val signingWellKnownIdentities = groupPublicKeysByWellKnownParty(serviceHub, stx.sigs.map(TransactionSignature::by), true)
|
||||||
require(otherSideSession.counterparty in signingWellKnownIdentities) {
|
require(otherSideSession.counterparty in signingWellKnownIdentities) {
|
||||||
"The Initiator of CollectSignaturesFlow must have signed the transaction. Found ${signingWellKnownIdentities}, expected ${otherSideSession}"
|
"The Initiator of CollectSignaturesFlow must have signed the transaction. Found $signingWellKnownIdentities, expected $otherSideSession"
|
||||||
}
|
}
|
||||||
val signed = stx.sigs.map { it.by }
|
val signed = stx.sigs.map { it.by }
|
||||||
val allSigners = stx.tx.requiredSigningKeys
|
val allSigners = stx.tx.requiredSigningKeys
|
||||||
@ -288,9 +291,10 @@ abstract class SignTransactionFlow(val otherSideSession: FlowSession,
|
|||||||
*/
|
*/
|
||||||
@Suspendable
|
@Suspendable
|
||||||
@Throws(FlowException::class)
|
@Throws(FlowException::class)
|
||||||
abstract protected fun checkTransaction(stx: SignedTransaction)
|
protected abstract fun checkTransaction(stx: SignedTransaction)
|
||||||
|
|
||||||
@Suspendable private fun checkMySignaturesRequired(stx: SignedTransaction, signingKeys: Iterable<PublicKey>) {
|
@Suspendable
|
||||||
|
private fun checkMySignaturesRequired(stx: SignedTransaction, signingKeys: Iterable<PublicKey>) {
|
||||||
require(signingKeys.all { it in stx.tx.requiredSigningKeys }) {
|
require(signingKeys.all { it in stx.tx.requiredSigningKeys }) {
|
||||||
"A signature was requested for a key that isn't part of the required signing keys for transaction ${stx.id}"
|
"A signature was requested for a key that isn't part of the required signing keys for transaction ${stx.id}"
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ open class FlowException(message: String?, cause: Throwable?) :
|
|||||||
constructor(message: String?) : this(message, null)
|
constructor(message: String?) : this(message, null)
|
||||||
constructor(cause: Throwable?) : this(cause?.toString(), cause)
|
constructor(cause: Throwable?) : this(cause?.toString(), cause)
|
||||||
constructor() : this(null, null)
|
constructor() : this(null, null)
|
||||||
|
|
||||||
var originalErrorId: Long? = null
|
var originalErrorId: Long? = null
|
||||||
override fun getErrorId(): Long? = originalErrorId
|
override fun getErrorId(): Long? = originalErrorId
|
||||||
}
|
}
|
||||||
@ -50,5 +51,6 @@ class UnexpectedFlowEndException(message: String, cause: Throwable?, val origina
|
|||||||
CordaRuntimeException(message, cause), IdentifiableException {
|
CordaRuntimeException(message, cause), IdentifiableException {
|
||||||
constructor(message: String, cause: Throwable?) : this(message, cause, null)
|
constructor(message: String, cause: Throwable?) : this(message, cause, null)
|
||||||
constructor(message: String) : this(message, null)
|
constructor(message: String) : this(message, null)
|
||||||
|
|
||||||
override fun getErrorId(): Long? = originalErrorId
|
override fun getErrorId(): Long? = originalErrorId
|
||||||
}
|
}
|
||||||
|
@ -60,20 +60,21 @@ sealed class FlowInitiator : Principal {
|
|||||||
* class hierarchy (which is now deprecated). The returned object has less information than it could have, so
|
* class hierarchy (which is now deprecated). The returned object has less information than it could have, so
|
||||||
* prefer to use fetch an invocation context directly if you can (e.g. in [net.corda.core.messaging.StateMachineInfo])
|
* prefer to use fetch an invocation context directly if you can (e.g. in [net.corda.core.messaging.StateMachineInfo])
|
||||||
*/
|
*/
|
||||||
val invocationContext: InvocationContext get() {
|
val invocationContext: InvocationContext
|
||||||
val unknownName = CordaX500Name("UNKNOWN", "UNKNOWN", "GB")
|
get() {
|
||||||
var actor: Actor? = null
|
val unknownName = CordaX500Name("UNKNOWN", "UNKNOWN", "GB")
|
||||||
val origin: InvocationOrigin
|
var actor: Actor? = null
|
||||||
when (this) {
|
val origin: InvocationOrigin
|
||||||
is FlowInitiator.RPC -> {
|
when (this) {
|
||||||
actor = Actor(Actor.Id(this.username), AuthServiceId("UNKNOWN"), unknownName)
|
is FlowInitiator.RPC -> {
|
||||||
origin = InvocationOrigin.RPC(actor)
|
actor = Actor(Actor.Id(this.username), AuthServiceId("UNKNOWN"), unknownName)
|
||||||
|
origin = InvocationOrigin.RPC(actor)
|
||||||
|
}
|
||||||
|
is FlowInitiator.Peer -> origin = InvocationOrigin.Peer(this.party.name)
|
||||||
|
is FlowInitiator.Service -> origin = InvocationOrigin.Service(this.serviceClassName, unknownName)
|
||||||
|
FlowInitiator.Shell -> origin = InvocationOrigin.Shell
|
||||||
|
is FlowInitiator.Scheduled -> origin = InvocationOrigin.Scheduled(this.scheduledState)
|
||||||
}
|
}
|
||||||
is FlowInitiator.Peer -> origin = InvocationOrigin.Peer(this.party.name)
|
return InvocationContext.newInstance(origin = origin, actor = actor)
|
||||||
is FlowInitiator.Service -> origin = InvocationOrigin.Service(this.serviceClassName, unknownName)
|
|
||||||
FlowInitiator.Shell -> origin = InvocationOrigin.Shell
|
|
||||||
is FlowInitiator.Scheduled -> origin = InvocationOrigin.Scheduled(this.scheduledState)
|
|
||||||
}
|
}
|
||||||
return InvocationContext.newInstance(origin = origin, actor = actor)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -128,9 +128,10 @@ data class CordaX500Name(val commonName: String?,
|
|||||||
private var _x500Principal: X500Principal? = null
|
private var _x500Principal: X500Principal? = null
|
||||||
|
|
||||||
/** Return the [X500Principal] equivalent of this name. */
|
/** Return the [X500Principal] equivalent of this name. */
|
||||||
val x500Principal: X500Principal get() {
|
val x500Principal: X500Principal
|
||||||
return _x500Principal ?: X500Principal(this.x500Name.encoded).also { _x500Principal = it }
|
get() {
|
||||||
}
|
return _x500Principal ?: X500Principal(this.x500Name.encoded).also { _x500Principal = it }
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String = x500Principal.toString()
|
override fun toString(): String = x500Principal.toString()
|
||||||
}
|
}
|
@ -60,7 +60,6 @@ object Emoji {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
val CODE_WARNING_SIGN: String = codePointsString(0x26A0, 0xFE0F)
|
val CODE_WARNING_SIGN: String = codePointsString(0x26A0, 0xFE0F)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When non-null, toString() methods are allowed to use emoji in the output as we're going to render them to a
|
* When non-null, toString() methods are allowed to use emoji in the output as we're going to render them to a
|
||||||
* sufficiently capable text surface.
|
* sufficiently capable text surface.
|
||||||
|
@ -145,7 +145,6 @@ sealed class FetchDataFlow<T : NamedByHash, in W : Any>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a set of hashes either loads from from local storage or requests them from the other peer. Downloaded
|
* Given a set of hashes either loads from from local storage or requests them from the other peer. Downloaded
|
||||||
* attachments are saved to local storage automatically.
|
* attachments are saved to local storage automatically.
|
||||||
|
@ -61,7 +61,8 @@ sealed class FlowIORequest<out R : Any> {
|
|||||||
val shouldRetrySend: Boolean
|
val shouldRetrySend: Boolean
|
||||||
) : FlowIORequest<Map<FlowSession, SerializedBytes<Any>>>() {
|
) : FlowIORequest<Map<FlowSession, SerializedBytes<Any>>>() {
|
||||||
override fun toString() = "SendAndReceive(${sessionToMessage.mapValues { (key, value) ->
|
override fun toString() = "SendAndReceive(${sessionToMessage.mapValues { (key, value) ->
|
||||||
"$key=${value.hash}" }}, shouldRetrySend=$shouldRetrySend)"
|
"$key=${value.hash}"
|
||||||
|
}}, shouldRetrySend=$shouldRetrySend)"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,10 +13,12 @@ package net.corda.core.internal
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.flows.*
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
|
||||||
import net.corda.core.context.InvocationContext
|
import net.corda.core.context.InvocationContext
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.FlowSession
|
||||||
|
import net.corda.core.flows.FlowStackSnapshot
|
||||||
|
import net.corda.core.flows.StateMachineRunId
|
||||||
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
|
|
||||||
|
@ -49,10 +49,10 @@ class LazyPool<A>(
|
|||||||
lifeCycle.requireState(State.STARTED)
|
lifeCycle.requireState(State.STARTED)
|
||||||
poolSemaphore.acquire()
|
poolSemaphore.acquire()
|
||||||
val pooled = poolQueue.poll()
|
val pooled = poolQueue.poll()
|
||||||
if (pooled == null) {
|
return if (pooled == null) {
|
||||||
return newInstance()
|
newInstance()
|
||||||
} else {
|
} else {
|
||||||
return clearIfNeeded(pooled)
|
clearIfNeeded(pooled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,6 @@ class LazyStickyPool<A : Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun close(): Iterable<A> {
|
fun close(): Iterable<A> {
|
||||||
return boxes.map { it.instance?.poll() }.filterNotNull()
|
return boxes.mapNotNull { it.instance?.poll() }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,4 +10,4 @@
|
|||||||
|
|
||||||
package net.corda.core.internal
|
package net.corda.core.internal
|
||||||
|
|
||||||
val STRUCTURAL_STEP_PREFIX = "Structural step change in child of "
|
const val STRUCTURAL_STEP_PREFIX = "Structural step change in child of "
|
@ -39,7 +39,7 @@ class X509EdDSAEngine : Signature {
|
|||||||
override fun engineInitVerify(publicKey: PublicKey) {
|
override fun engineInitVerify(publicKey: PublicKey) {
|
||||||
val parsedKey = try {
|
val parsedKey = try {
|
||||||
publicKey as? EdDSAPublicKey ?: EdDSAPublicKey(X509EncodedKeySpec(publicKey.encoded))
|
publicKey as? EdDSAPublicKey ?: EdDSAPublicKey(X509EncodedKeySpec(publicKey.encoded))
|
||||||
} catch(e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw (InvalidKeyException(e.message))
|
throw (InvalidKeyException(e.message))
|
||||||
}
|
}
|
||||||
engine.initVerify(parsedKey)
|
engine.initVerify(parsedKey)
|
||||||
@ -53,9 +53,9 @@ class X509EdDSAEngine : Signature {
|
|||||||
|
|
||||||
override fun engineGetParameters(): AlgorithmParameters = engine.parameters
|
override fun engineGetParameters(): AlgorithmParameters = engine.parameters
|
||||||
override fun engineSetParameter(params: AlgorithmParameterSpec) = engine.setParameter(params)
|
override fun engineSetParameter(params: AlgorithmParameterSpec) = engine.setParameter(params)
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION", "OverridingDeprecatedMember")
|
||||||
override fun engineGetParameter(param: String): Any = engine.getParameter(param)
|
override fun engineGetParameter(param: String): Any = engine.getParameter(param)
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION", "OverridingDeprecatedMember")
|
||||||
override fun engineSetParameter(param: String, value: Any?) = engine.setParameter(param, value)
|
override fun engineSetParameter(param: String, value: Any?) = engine.setParameter(param, value)
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ interface OpenFuture<V> : ValueOrException<V>, CordaFuture<V>
|
|||||||
internal class CordaFutureImpl<V>(private val impl: CompletableFuture<V> = CompletableFuture()) : Future<V> by impl, OpenFuture<V> {
|
internal class CordaFutureImpl<V>(private val impl: CompletableFuture<V> = CompletableFuture()) : Future<V> by impl, OpenFuture<V> {
|
||||||
companion object {
|
companion object {
|
||||||
private val defaultLog = contextLogger()
|
private val defaultLog = contextLogger()
|
||||||
internal val listenerFailedMessage = "Future listener failed:"
|
internal const val listenerFailedMessage = "Future listener failed:"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun set(value: V) = impl.complete(value)
|
override fun set(value: V) = impl.complete(value)
|
||||||
|
@ -23,7 +23,7 @@ data class CordappImpl(
|
|||||||
override val contractClassNames: List<String>,
|
override val contractClassNames: List<String>,
|
||||||
override val initiatedFlows: List<Class<out FlowLogic<*>>>,
|
override val initiatedFlows: List<Class<out FlowLogic<*>>>,
|
||||||
override val rpcFlows: List<Class<out FlowLogic<*>>>,
|
override val rpcFlows: List<Class<out FlowLogic<*>>>,
|
||||||
override val serviceFlows: List<Class<out FlowLogic<*>>>,
|
override val serviceFlows: List<Class<out FlowLogic<*>>>,
|
||||||
override val schedulableFlows: List<Class<out FlowLogic<*>>>,
|
override val schedulableFlows: List<Class<out FlowLogic<*>>>,
|
||||||
override val services: List<Class<out SerializeAsToken>>,
|
override val services: List<Class<out SerializeAsToken>>,
|
||||||
override val serializationWhitelists: List<SerializationWhitelist>,
|
override val serializationWhitelists: List<SerializationWhitelist>,
|
||||||
|
@ -64,7 +64,6 @@ interface FlowProgressHandle<A> : FlowHandle<A> {
|
|||||||
override fun close()
|
override fun close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class FlowHandleImpl<A>(
|
data class FlowHandleImpl<A>(
|
||||||
override val id: StateMachineRunId,
|
override val id: StateMachineRunId,
|
||||||
|
@ -36,5 +36,4 @@ interface AppServiceHub : ServiceHub {
|
|||||||
* TODO it is assumed here that the flow object has an appropriate classloader.
|
* TODO it is assumed here that the flow object has an appropriate classloader.
|
||||||
*/
|
*/
|
||||||
fun <T> startTrackedFlow(flow: FlowLogic<T>): FlowProgressHandle<T>
|
fun <T> startTrackedFlow(flow: FlowLogic<T>): FlowProgressHandle<T>
|
||||||
|
|
||||||
}
|
}
|
@ -41,7 +41,8 @@ data class NodeInfo(val addresses: List<NetworkHostAndPort>,
|
|||||||
require(platformVersion > 0) { "Platform version must be at least 1" }
|
require(platformVersion > 0) { "Platform version must be at least 1" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient private var _legalIdentities: List<Party>? = null
|
@Transient
|
||||||
|
private var _legalIdentities: List<Party>? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ordered list of legal identities supported by this node. The node will always have at least one, so if you
|
* An ordered list of legal identities supported by this node. The node will always have at least one, so if you
|
||||||
|
@ -253,7 +253,7 @@ object Builder {
|
|||||||
fun <R> Field.functionPredicate(predicate: ColumnPredicate<R>, groupByColumns: List<Column<Any, R>>? = null, orderBy: Sort.Direction? = null) = info().functionPredicate(predicate, groupByColumns, orderBy)
|
fun <R> Field.functionPredicate(predicate: ColumnPredicate<R>, groupByColumns: List<Column<Any, R>>? = null, orderBy: Sort.Direction? = null) = info().functionPredicate(predicate, groupByColumns, orderBy)
|
||||||
|
|
||||||
fun <R> FieldInfo.functionPredicate(predicate: ColumnPredicate<R>, groupByColumns: List<Column<Any, R>>? = null, orderBy: Sort.Direction? = null)
|
fun <R> FieldInfo.functionPredicate(predicate: ColumnPredicate<R>, groupByColumns: List<Column<Any, R>>? = null, orderBy: Sort.Direction? = null)
|
||||||
= CriteriaExpression.AggregateFunctionExpression(Column<Any, R>(this), predicate, groupByColumns, orderBy)
|
= CriteriaExpression.AggregateFunctionExpression(Column(this), predicate, groupByColumns, orderBy)
|
||||||
|
|
||||||
fun <O, R : Comparable<R>> KProperty1<O, R?>.comparePredicate(operator: BinaryComparisonOperator, value: R) = predicate(compare(operator, value))
|
fun <O, R : Comparable<R>> KProperty1<O, R?>.comparePredicate(operator: BinaryComparisonOperator, value: R) = predicate(compare(operator, value))
|
||||||
@Deprecated("Does not support fields from a MappedSuperclass. Use equivalent on a FieldInfo.")
|
@Deprecated("Does not support fields from a MappedSuperclass. Use equivalent on a FieldInfo.")
|
||||||
@ -377,7 +377,7 @@ object Builder {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun <R> FieldInfo.sum(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
fun <R> FieldInfo.sum(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
||||||
functionPredicate(ColumnPredicate.AggregateFunction<R>(AggregateFunctionType.SUM), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.SUM), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
||||||
|
|
||||||
fun <O, R> KProperty1<O, R?>.count() = functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.COUNT))
|
fun <O, R> KProperty1<O, R?>.count() = functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.COUNT))
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ -397,7 +397,7 @@ object Builder {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun <R> FieldInfo.avg(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
fun <R> FieldInfo.avg(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
||||||
functionPredicate(ColumnPredicate.AggregateFunction<R>(AggregateFunctionType.AVG), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.AVG), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
||||||
|
|
||||||
fun <O, R> KProperty1<O, R?>.min(groupByColumns: List<KProperty1<O, R>>? = null, orderBy: Sort.Direction? = null) =
|
fun <O, R> KProperty1<O, R?>.min(groupByColumns: List<KProperty1<O, R>>? = null, orderBy: Sort.Direction? = null) =
|
||||||
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.MIN), groupByColumns?.map { Column(it) }, orderBy)
|
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.MIN), groupByColumns?.map { Column(it) }, orderBy)
|
||||||
@ -410,7 +410,7 @@ object Builder {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun <R> FieldInfo.min(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
fun <R> FieldInfo.min(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
||||||
functionPredicate(ColumnPredicate.AggregateFunction<R>(AggregateFunctionType.MIN), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.MIN), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
||||||
|
|
||||||
fun <O, R> KProperty1<O, R?>.max(groupByColumns: List<KProperty1<O, R>>? = null, orderBy: Sort.Direction? = null) =
|
fun <O, R> KProperty1<O, R?>.max(groupByColumns: List<KProperty1<O, R>>? = null, orderBy: Sort.Direction? = null) =
|
||||||
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.MAX), groupByColumns?.map { Column(it) }, orderBy)
|
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.MAX), groupByColumns?.map { Column(it) }, orderBy)
|
||||||
@ -423,7 +423,7 @@ object Builder {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun <R> FieldInfo.max(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
fun <R> FieldInfo.max(groupByColumns: List<FieldInfo>? = null, orderBy: Sort.Direction? = null) =
|
||||||
functionPredicate(ColumnPredicate.AggregateFunction<R>(AggregateFunctionType.MAX), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
functionPredicate(ColumnPredicate.AggregateFunction(AggregateFunctionType.MAX), groupByColumns?.map { Column<Any, R>(it) }, orderBy)
|
||||||
|
|
||||||
private fun Field.info(): FieldInfo = FieldInfo(name, declaringClass)
|
private fun Field.info(): FieldInfo = FieldInfo(name, declaringClass)
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers
|
|||||||
override val migrationResource = "common.changelog-master"
|
override val migrationResource = "common.changelog-master"
|
||||||
|
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
open class LinearState(
|
class LinearState(
|
||||||
/** [ContractState] attributes */
|
/** [ContractState] attributes */
|
||||||
|
|
||||||
/** X500Name of participant parties **/
|
/** X500Name of participant parties **/
|
||||||
@ -56,7 +56,7 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers
|
|||||||
}
|
}
|
||||||
|
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
open class FungibleState(
|
class FungibleState(
|
||||||
/** [ContractState] attributes */
|
/** [ContractState] attributes */
|
||||||
|
|
||||||
/** X500Name of participant parties **/
|
/** X500Name of participant parties **/
|
||||||
|
@ -89,7 +89,8 @@ open class MappedSchema(schemaFamily: Class<*>,
|
|||||||
* [StateRef] will be set to the correct value by the framework (there's no need to set during mapping generation by the state itself).
|
* [StateRef] will be set to the correct value by the framework (there's no need to set during mapping generation by the state itself).
|
||||||
*/
|
*/
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
@CordaSerializable open class PersistentState(@EmbeddedId var stateRef: PersistentStateRef? = null) : StatePersistable
|
@CordaSerializable
|
||||||
|
class PersistentState(@EmbeddedId var stateRef: PersistentStateRef? = null) : StatePersistable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Embedded [StateRef] representation used in state mapping.
|
* Embedded [StateRef] representation used in state mapping.
|
||||||
|
@ -24,11 +24,11 @@ interface SerializationCustomSerializer<OBJ, PROXY> {
|
|||||||
* Should facilitate the conversion of the third party object into the serializable
|
* Should facilitate the conversion of the third party object into the serializable
|
||||||
* local class specified by [PROXY]
|
* local class specified by [PROXY]
|
||||||
*/
|
*/
|
||||||
fun toProxy(obj: OBJ) : PROXY
|
fun toProxy(obj: OBJ): PROXY
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should facilitate the conversion of the proxy object into a new instance of the
|
* Should facilitate the conversion of the proxy object into a new instance of the
|
||||||
* unserializable type
|
* unserializable type
|
||||||
*/
|
*/
|
||||||
fun fromProxy(proxy: PROXY) : OBJ
|
fun fromProxy(proxy: PROXY): OBJ
|
||||||
}
|
}
|
||||||
|
@ -222,17 +222,17 @@ data class ContractUpgradeLedgerTransaction(
|
|||||||
* Outputs are computed by running the contract upgrade logic on input states. This is done eagerly so that the
|
* Outputs are computed by running the contract upgrade logic on input states. This is done eagerly so that the
|
||||||
* transaction is verified during construction.
|
* transaction is verified during construction.
|
||||||
*/
|
*/
|
||||||
override val outputs: List<TransactionState<ContractState>> = inputs.map { input ->
|
override val outputs: List<TransactionState<ContractState>> = inputs.map { (state) ->
|
||||||
// TODO: if there are encumbrance states in the inputs, just copy them across without modifying
|
// TODO: if there are encumbrance states in the inputs, just copy them across without modifying
|
||||||
val upgradedState = upgradedContract.upgrade(input.state.data)
|
val upgradedState = upgradedContract.upgrade(state.data)
|
||||||
val inputConstraint = input.state.constraint
|
val inputConstraint = state.constraint
|
||||||
val outputConstraint = when (inputConstraint) {
|
val outputConstraint = when (inputConstraint) {
|
||||||
is HashAttachmentConstraint -> HashAttachmentConstraint(upgradedContractAttachment.id)
|
is HashAttachmentConstraint -> HashAttachmentConstraint(upgradedContractAttachment.id)
|
||||||
WhitelistedByZoneAttachmentConstraint -> WhitelistedByZoneAttachmentConstraint
|
WhitelistedByZoneAttachmentConstraint -> WhitelistedByZoneAttachmentConstraint
|
||||||
else -> throw IllegalArgumentException("Unsupported input contract constraint $inputConstraint")
|
else -> throw IllegalArgumentException("Unsupported input contract constraint $inputConstraint")
|
||||||
}
|
}
|
||||||
// TODO: re-map encumbrance pointers
|
// TODO: re-map encumbrance pointers
|
||||||
input.state.copy(
|
state.copy(
|
||||||
data = upgradedState,
|
data = upgradedState,
|
||||||
contract = upgradedContractClassName,
|
contract = upgradedContractClassName,
|
||||||
constraint = outputConstraint
|
constraint = outputConstraint
|
||||||
|
@ -116,7 +116,7 @@ class WireTransaction(componentGroups: List<ComponentGroup>, val privacySalt: Pr
|
|||||||
resolveIdentity: (PublicKey) -> Party?,
|
resolveIdentity: (PublicKey) -> Party?,
|
||||||
resolveAttachment: (SecureHash) -> Attachment?,
|
resolveAttachment: (SecureHash) -> Attachment?,
|
||||||
resolveStateRef: (StateRef) -> TransactionState<*>?,
|
resolveStateRef: (StateRef) -> TransactionState<*>?,
|
||||||
resolveContractAttachment: (TransactionState<ContractState>) -> AttachmentId?
|
@SuppressWarnings("unused") resolveContractAttachment: (TransactionState<ContractState>) -> AttachmentId?
|
||||||
): LedgerTransaction {
|
): LedgerTransaction {
|
||||||
return toLedgerTransactionInternal(resolveIdentity, resolveAttachment, resolveStateRef, null)
|
return toLedgerTransactionInternal(resolveIdentity, resolveAttachment, resolveStateRef, null)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ fun ByteArray.toBase64(): String = Base64.getEncoder().encodeToString(this)
|
|||||||
/** Convert a byte array to a hex (Base16) capitalized encoded [String]. */
|
/** Convert a byte array to a hex (Base16) capitalized encoded [String]. */
|
||||||
fun ByteArray.toHex(): String = DatatypeConverter.printHexBinary(this)
|
fun ByteArray.toHex(): String = DatatypeConverter.printHexBinary(this)
|
||||||
|
|
||||||
|
|
||||||
// [String] encoders and decoders
|
// [String] encoders and decoders
|
||||||
|
|
||||||
/** Base58-String to the actual real [String], i.e. "JxF12TrwUP45BMd" -> "Hello World". */
|
/** Base58-String to the actual real [String], i.e. "JxF12TrwUP45BMd" -> "Hello World". */
|
||||||
@ -60,7 +59,6 @@ fun String.base64ToByteArray(): ByteArray = Base64.getDecoder().decode(this)
|
|||||||
/** Hex-String to [ByteArray]. Accept any hex form (capitalized, lowercase, mixed). */
|
/** Hex-String to [ByteArray]. Accept any hex form (capitalized, lowercase, mixed). */
|
||||||
fun String.hexToByteArray(): ByteArray = DatatypeConverter.parseHexBinary(this)
|
fun String.hexToByteArray(): ByteArray = DatatypeConverter.parseHexBinary(this)
|
||||||
|
|
||||||
|
|
||||||
// Encoding changers
|
// Encoding changers
|
||||||
|
|
||||||
/** Encoding changer. Base58-[String] to Base64-[String], i.e. "SGVsbG8gV29ybGQ=" -> JxF12TrwUP45BMd" */
|
/** Encoding changer. Base58-[String] to Base64-[String], i.e. "SGVsbG8gV29ybGQ=" -> JxF12TrwUP45BMd" */
|
||||||
|
@ -116,8 +116,10 @@ interface VariablePropertyDelegate<T> : PropertyDelegate<T> {
|
|||||||
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
private class TransientProperty<out T> internal constructor(private val initialiser: () -> T) : PropertyDelegate<T> {
|
private class TransientProperty<out T> internal constructor(private val initialiser: () -> T) : PropertyDelegate<T> {
|
||||||
@Transient private var initialised = false
|
@Transient
|
||||||
@Transient private var value: T? = null
|
private var initialised = false
|
||||||
|
@Transient
|
||||||
|
private var value: T? = null
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
override operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||||
|
@ -71,11 +71,11 @@ class ProgressTracker(vararg steps: Step) {
|
|||||||
|
|
||||||
// Sentinel objects. Overrides equals() to survive process restarts and serialization.
|
// Sentinel objects. Overrides equals() to survive process restarts and serialization.
|
||||||
object UNSTARTED : Step("Unstarted") {
|
object UNSTARTED : Step("Unstarted") {
|
||||||
override fun equals(other: Any?) = other is UNSTARTED
|
override fun equals(other: Any?) = other === UNSTARTED
|
||||||
}
|
}
|
||||||
|
|
||||||
object DONE : Step("Done") {
|
object DONE : Step("Done") {
|
||||||
override fun equals(other: Any?) = other is DONE
|
override fun equals(other: Any?) = other === DONE
|
||||||
}
|
}
|
||||||
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
|
@ -50,7 +50,6 @@ fun <T : Any> SerializedBytes<Any>.checkPayloadIs(type: Class<T>): Untrustworthy
|
|||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
throw IllegalArgumentException("Payload invalid", ex)
|
throw IllegalArgumentException("Payload invalid", ex)
|
||||||
}
|
}
|
||||||
return type.castIfPossible(payloadData)?.let { UntrustworthyData(it) } ?:
|
return type.castIfPossible(payloadData)?.let { UntrustworthyData(it) } ?: throw IllegalArgumentException("We were expecting a ${type.name} but we instead got a " +
|
||||||
throw IllegalArgumentException("We were expecting a ${type.name} but we instead got a " +
|
"${payloadData.javaClass.name} ($payloadData)")
|
||||||
"${payloadData.javaClass.name} (${payloadData})")
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,6 @@ import java.util.*
|
|||||||
class UuidGenerator {
|
class UuidGenerator {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun next() : UUID = UUID.randomUUID()
|
fun next(): UUID = UUID.randomUUID()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -35,7 +35,7 @@ public class FlowsInJavaTest {
|
|||||||
private Party bob;
|
private Party bob;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() {
|
||||||
aliceNode = mockNet.createPartyNode(TestConstants.ALICE_NAME);
|
aliceNode = mockNet.createPartyNode(TestConstants.ALICE_NAME);
|
||||||
bobNode = mockNet.createPartyNode(TestConstants.BOB_NAME);
|
bobNode = mockNet.createPartyNode(TestConstants.BOB_NAME);
|
||||||
bob = singleIdentity(bobNode.getInfo());
|
bob = singleIdentity(bobNode.getInfo());
|
||||||
@ -134,7 +134,7 @@ public class FlowsInJavaTest {
|
|||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
@Override
|
@Override
|
||||||
public Void call() throws FlowException {
|
public Void call() {
|
||||||
FlowSession session = initiateFlow(otherParty);
|
FlowSession session = initiateFlow(otherParty);
|
||||||
session.receive(Primitives.unwrap(receiveType));
|
session.receive(Primitives.unwrap(receiveType));
|
||||||
return null;
|
return null;
|
||||||
|
@ -51,7 +51,6 @@ class AttachmentTest {
|
|||||||
}
|
}
|
||||||
assertEquals(1, closeCalls)
|
assertEquals(1, closeCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniqueIdentifierTests {
|
class UniqueIdentifierTests {
|
||||||
@ -83,5 +82,4 @@ class UniqueIdentifierTests {
|
|||||||
assertEquals(ids[1], ids[2])
|
assertEquals(ids[1], ids[2])
|
||||||
assertEquals(ids[1].hashCode(), ids[2].hashCode())
|
assertEquals(ids[1].hashCode(), ids[2].hashCode())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -186,9 +186,9 @@ class EdDSATests {
|
|||||||
|
|
||||||
/** A test vector object for digital signature schemes. */
|
/** A test vector object for digital signature schemes. */
|
||||||
private data class SignatureTestVector(val privateKeyHex: String,
|
private data class SignatureTestVector(val privateKeyHex: String,
|
||||||
val publicKeyHex: String,
|
val publicKeyHex: String,
|
||||||
val messageToSignHex: String,
|
val messageToSignHex: String,
|
||||||
val signatureOutputHex: String)
|
val signatureOutputHex: String)
|
||||||
|
|
||||||
// Required to implement a custom doSign function, because Corda's Crypto.doSign does not allow empty messages (testVector1).
|
// Required to implement a custom doSign function, because Corda's Crypto.doSign does not allow empty messages (testVector1).
|
||||||
private fun doSign(privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
private fun doSign(privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
||||||
|
@ -136,6 +136,5 @@ class X509NameConstraintsTest {
|
|||||||
pathValidator.validate(certPath, params)
|
pathValidator.validate(certPath, params)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ package net.corda.core.flows
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.contracts.Attachment
|
import net.corda.core.contracts.Attachment
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.sha256
|
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.FetchAttachmentsFlow
|
import net.corda.core.internal.FetchAttachmentsFlow
|
||||||
import net.corda.core.internal.FetchDataFlow
|
import net.corda.core.internal.FetchDataFlow
|
||||||
@ -92,7 +91,7 @@ class AttachmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `missing`() {
|
fun missing() {
|
||||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||||
aliceNode.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
aliceNode.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||||
|
@ -23,7 +23,11 @@ import net.corda.core.transactions.TransactionBuilder
|
|||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.core.*
|
import net.corda.testing.core.ALICE_NAME
|
||||||
|
import net.corda.testing.core.BOB_NAME
|
||||||
|
import net.corda.testing.core.CHARLIE_NAME
|
||||||
|
import net.corda.testing.core.TestIdentity
|
||||||
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.internal.rigorousMock
|
import net.corda.testing.internal.rigorousMock
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import net.corda.testing.node.internal.InternalMockNetwork
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
@ -32,7 +36,6 @@ import net.corda.testing.node.internal.startFlow
|
|||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.reflect.KClass
|
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class CollectSignaturesFlowTests {
|
class CollectSignaturesFlowTests {
|
||||||
@ -86,9 +89,11 @@ class CollectSignaturesFlowTests {
|
|||||||
|
|
||||||
@InitiatedBy(TestFlow.Initiator::class)
|
@InitiatedBy(TestFlow.Initiator::class)
|
||||||
class Responder(private val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
class Responder(private val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
||||||
@Suspendable override fun call() {
|
@Suspendable
|
||||||
|
override fun call() {
|
||||||
val signFlow = object : SignTransactionFlow(otherSideSession) {
|
val signFlow = object : SignTransactionFlow(otherSideSession) {
|
||||||
@Suspendable override fun checkTransaction(stx: SignedTransaction) = requireThat {
|
@Suspendable
|
||||||
|
override fun checkTransaction(stx: SignedTransaction) = requireThat {
|
||||||
val tx = stx.tx
|
val tx = stx.tx
|
||||||
val ltx = tx.toLedgerTransaction(serviceHub)
|
val ltx = tx.toLedgerTransaction(serviceHub)
|
||||||
"There should only be one output state" using (tx.outputs.size == 1)
|
"There should only be one output state" using (tx.outputs.size == 1)
|
||||||
|
@ -33,7 +33,7 @@ class PartyAndCertificateTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `reject a path with no roles`() {
|
fun `reject a path with no roles`() {
|
||||||
val path = X509Utilities.buildCertPath(DEV_ROOT_CA.certificate)
|
val path = X509Utilities.buildCertPath(DEV_ROOT_CA.certificate)
|
||||||
assertFailsWith<IllegalArgumentException> { PartyAndCertificate(path) }
|
assertFailsWith<IllegalArgumentException> { PartyAndCertificate(path) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import kotlin.test.assertNotEquals
|
|||||||
|
|
||||||
class PartyTest {
|
class PartyTest {
|
||||||
@Test
|
@Test
|
||||||
fun `equality`() {
|
fun equality() {
|
||||||
val key = entropyToKeyPair(BigInteger.valueOf(20170207L)).public
|
val key = entropyToKeyPair(BigInteger.valueOf(20170207L)).public
|
||||||
val differentKey = entropyToKeyPair(BigInteger.valueOf(7201702L)).public
|
val differentKey = entropyToKeyPair(BigInteger.valueOf(7201702L)).public
|
||||||
val anonymousParty = AnonymousParty(key)
|
val anonymousParty = AnonymousParty(key)
|
||||||
|
@ -21,7 +21,6 @@ import org.junit.Test
|
|||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.streams.toList
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class AbstractAttachmentTest {
|
class AbstractAttachmentTest {
|
||||||
|
@ -71,7 +71,7 @@ class LegalNameValidatorTest {
|
|||||||
}
|
}
|
||||||
// Latin capital letter turned m
|
// Latin capital letter turned m
|
||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
LegalNameValidator.validateOrganization( "Test\u019CLtd", LegalNameValidator.Validation.FULL)
|
LegalNameValidator.validateOrganization("Test\u019CLtd", LegalNameValidator.Validation.FULL)
|
||||||
}
|
}
|
||||||
// Latin small letter turned e
|
// Latin small letter turned e
|
||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
@ -94,7 +94,7 @@ class LegalNameValidatorTest {
|
|||||||
}
|
}
|
||||||
// Latin capital letter turned m
|
// Latin capital letter turned m
|
||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
LegalNameValidator.validateNameAttribute( "Test\u019CLtd", LegalNameValidator.Validation.FULL)
|
LegalNameValidator.validateNameAttribute("Test\u019CLtd", LegalNameValidator.Validation.FULL)
|
||||||
}
|
}
|
||||||
// Latin small letter turned e
|
// Latin small letter turned e
|
||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
|
@ -24,7 +24,7 @@ import kotlin.test.assertFailsWith
|
|||||||
|
|
||||||
class VaultUpdateTests {
|
class VaultUpdateTests {
|
||||||
private companion object {
|
private companion object {
|
||||||
val DUMMY_PROGRAM_ID = "net.corda.core.node.VaultUpdateTests.DummyContract"
|
const val DUMMY_PROGRAM_ID = "net.corda.core.node.VaultUpdateTests.DummyContract"
|
||||||
val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
|
val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
|
||||||
val emptyUpdate = Vault.Update(emptySet(), emptySet(), type = Vault.UpdateType.GENERAL)
|
val emptyUpdate = Vault.Update(emptySet(), emptySet(), type = Vault.UpdateType.GENERAL)
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ class VaultUpdateTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `nothing plus something is something`() {
|
fun `nothing plus something is something`() {
|
||||||
val before = emptyUpdate
|
val before = emptyUpdate
|
||||||
val after = before + Vault.Update<ContractState>(setOf(stateAndRef0, stateAndRef1), setOf(stateAndRef2, stateAndRef3))
|
val after = before + Vault.Update(setOf(stateAndRef0, stateAndRef1), setOf(stateAndRef2, stateAndRef3))
|
||||||
val expected = Vault.Update<ContractState>(setOf(stateAndRef0, stateAndRef1), setOf(stateAndRef2, stateAndRef3))
|
val expected = Vault.Update<ContractState>(setOf(stateAndRef0, stateAndRef1), setOf(stateAndRef2, stateAndRef3))
|
||||||
assertEquals(expected, after)
|
assertEquals(expected, after)
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ class VaultUpdateTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `something plus consume state 0 is something without state 0 output`() {
|
fun `something plus consume state 0 is something without state 0 output`() {
|
||||||
val before = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1))
|
val before = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1))
|
||||||
val after = before + Vault.Update<ContractState>(setOf(stateAndRef0), setOf())
|
val after = before + Vault.Update(setOf(stateAndRef0), setOf())
|
||||||
val expected = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef1))
|
val expected = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef1))
|
||||||
assertEquals(expected, after)
|
assertEquals(expected, after)
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ class VaultUpdateTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `something plus produce state 4 is something with additional state 4 output`() {
|
fun `something plus produce state 4 is something with additional state 4 output`() {
|
||||||
val before = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1))
|
val before = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1))
|
||||||
val after = before + Vault.Update<ContractState>(setOf(), setOf(stateAndRef4))
|
val after = before + Vault.Update(setOf(), setOf(stateAndRef4))
|
||||||
val expected = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1, stateAndRef4))
|
val expected = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1, stateAndRef4))
|
||||||
assertEquals(expected, after)
|
assertEquals(expected, after)
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ class VaultUpdateTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `something plus consume states 0 and 1, and produce state 4, is something without state 0 and 1 outputs and only state 4 output`() {
|
fun `something plus consume states 0 and 1, and produce state 4, is something without state 0 and 1 outputs and only state 4 output`() {
|
||||||
val before = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1))
|
val before = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef0, stateAndRef1))
|
||||||
val after = before + Vault.Update<ContractState>(setOf(stateAndRef0, stateAndRef1), setOf(stateAndRef4))
|
val after = before + Vault.Update(setOf(stateAndRef0, stateAndRef1), setOf(stateAndRef4))
|
||||||
val expected = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef4))
|
val expected = Vault.Update<ContractState>(setOf(stateAndRef2, stateAndRef3), setOf(stateAndRef4))
|
||||||
assertEquals(expected, after)
|
assertEquals(expected, after)
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ private fun createAttachmentData(content: String) = ByteArrayOutputStream().appl
|
|||||||
|
|
||||||
private fun Attachment.extractContent() = ByteArrayOutputStream().apply { extractFile("content", this) }.toString(UTF_8.name())
|
private fun Attachment.extractContent() = ByteArrayOutputStream().apply { extractFile("content", this) }.toString(UTF_8.name())
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private fun StartedNode<*>.saveAttachment(content: String) = database.transaction {
|
private fun StartedNode<*>.saveAttachment(content: String) = database.transaction {
|
||||||
attachments.importAttachment(createAttachmentData(content).inputStream())
|
attachments.importAttachment(createAttachmentData(content).inputStream())
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ class TransactionSerializationTests {
|
|||||||
stx.verifyRequiredSignatures()
|
stx.verifyRequiredSignatures()
|
||||||
|
|
||||||
// Corrupt the data and ensure the signature catches the problem.
|
// Corrupt the data and ensure the signature catches the problem.
|
||||||
val bytesField = stx.id::bytes.javaField?.apply { setAccessible(true) }
|
val bytesField = stx.id::bytes.javaField?.apply { isAccessible = true }
|
||||||
val bytes = bytesField?.get(stx.id) as ByteArray
|
val bytes = bytesField?.get(stx.id) as ByteArray
|
||||||
bytes[5] = bytes[5].inc()
|
bytes[5] = bytes[5].inc()
|
||||||
|
|
||||||
|
@ -62,12 +62,12 @@ class CompatibleTransactionTests {
|
|||||||
// Do not add attachments (empty list).
|
// Do not add attachments (empty list).
|
||||||
private val componentGroupsA by lazy {
|
private val componentGroupsA by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
inputGroup,
|
inputGroup,
|
||||||
outputGroup,
|
outputGroup,
|
||||||
commandGroup,
|
commandGroup,
|
||||||
notaryGroup,
|
notaryGroup,
|
||||||
timeWindowGroup,
|
timeWindowGroup,
|
||||||
signersGroup
|
signersGroup
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
private val wireTransactionA by lazy { WireTransaction(componentGroups = componentGroupsA, privacySalt = privacySalt) }
|
private val wireTransactionA by lazy { WireTransaction(componentGroups = componentGroupsA, privacySalt = privacySalt) }
|
||||||
@ -134,7 +134,8 @@ class CompatibleTransactionTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `WireTransaction constructors and compatibility`() {
|
fun `WireTransaction constructors and compatibility`() {
|
||||||
val wireTransactionOldConstructor = WireTransaction(inputs, attachments, outputs, commands, notary, timeWindow, privacySalt)
|
val groups = WireTransaction.createComponentGroups(inputs, outputs, commands, attachments, notary, timeWindow)
|
||||||
|
val wireTransactionOldConstructor = WireTransaction(groups, privacySalt)
|
||||||
assertEquals(wireTransactionA, wireTransactionOldConstructor)
|
assertEquals(wireTransactionA, wireTransactionOldConstructor)
|
||||||
|
|
||||||
// Malformed tx - attachments is not List<SecureHash>. For this example, we mistakenly added input-state (StateRef) serialised objects with ATTACHMENTS_GROUP.ordinal.
|
// Malformed tx - attachments is not List<SecureHash>. For this example, we mistakenly added input-state (StateRef) serialised objects with ATTACHMENTS_GROUP.ordinal.
|
||||||
@ -396,7 +397,7 @@ class CompatibleTransactionTests {
|
|||||||
assertFailsWith<IllegalStateException> { WireTransaction(componentGroups = componentGroupsLessSigners, privacySalt = PrivacySalt()) }
|
assertFailsWith<IllegalStateException> { WireTransaction(componentGroups = componentGroupsLessSigners, privacySalt = PrivacySalt()) }
|
||||||
|
|
||||||
// Test if there is no command to sign.
|
// Test if there is no command to sign.
|
||||||
val commandsNoKey1= listOf(dummyCommand(DUMMY_KEY_2.public))
|
val commandsNoKey1 = listOf(dummyCommand(DUMMY_KEY_2.public))
|
||||||
|
|
||||||
val componentGroupsNoKey1ToSign = listOf(
|
val componentGroupsNoKey1ToSign = listOf(
|
||||||
inputGroup,
|
inputGroup,
|
||||||
@ -409,7 +410,7 @@ class CompatibleTransactionTests {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val wtxNoKey1 = WireTransaction(componentGroups = componentGroupsNoKey1ToSign, privacySalt = PrivacySalt())
|
val wtxNoKey1 = WireTransaction(componentGroups = componentGroupsNoKey1ToSign, privacySalt = PrivacySalt())
|
||||||
val allCommandsNoKey1Ftx= wtxNoKey1.buildFilteredTransaction(Predicate(::filterCommandsOnly))
|
val allCommandsNoKey1Ftx = wtxNoKey1.buildFilteredTransaction(Predicate(::filterCommandsOnly))
|
||||||
allCommandsNoKey1Ftx.checkCommandVisibility(DUMMY_KEY_1.public) // This will pass, because there are indeed no commands to sign in the original transaction.
|
allCommandsNoKey1Ftx.checkCommandVisibility(DUMMY_KEY_1.public) // This will pass, because there are indeed no commands to sign in the original transaction.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +501,7 @@ class CompatibleTransactionTests {
|
|||||||
// Remove both last signer (KEY1) and related command.
|
// Remove both last signer (KEY1) and related command.
|
||||||
// Update partial Merkle tree for signers.
|
// Update partial Merkle tree for signers.
|
||||||
val updatedFilteredComponentsNoLastCommandAndSigners = listOf(noLastCommandDataGroup, noLastSignerGroup)
|
val updatedFilteredComponentsNoLastCommandAndSigners = listOf(noLastCommandDataGroup, noLastSignerGroup)
|
||||||
val ftxNoLastCommandAndSigners = ftxConstructor.invoke(key1CommandsFtx.id, updatedFilteredComponentsNoLastCommandAndSigners, key1CommandsFtx.groupHashes) as FilteredTransaction
|
val ftxNoLastCommandAndSigners = ftxConstructor.invoke(key1CommandsFtx.id, updatedFilteredComponentsNoLastCommandAndSigners, key1CommandsFtx.groupHashes)
|
||||||
// verify() will pass as the transaction is well-formed.
|
// verify() will pass as the transaction is well-formed.
|
||||||
ftxNoLastCommandAndSigners.verify()
|
ftxNoLastCommandAndSigners.verify()
|
||||||
// checkCommandVisibility() will not pass, because checkAllComponentsVisible(ComponentGroupEnum.SIGNERS_GROUP) will fail.
|
// checkCommandVisibility() will not pass, because checkAllComponentsVisible(ComponentGroupEnum.SIGNERS_GROUP) will fail.
|
||||||
@ -509,7 +510,7 @@ class CompatibleTransactionTests {
|
|||||||
// Remove last signer for which there is no pointer from a visible commandData. This is the case of Key2.
|
// Remove last signer for which there is no pointer from a visible commandData. This is the case of Key2.
|
||||||
// Do not change partial Merkle tree for signers.
|
// Do not change partial Merkle tree for signers.
|
||||||
// This time the object can be constructed as there is no pointer mismatch.
|
// This time the object can be constructed as there is no pointer mismatch.
|
||||||
val ftxNoLastSigner = ftxConstructor.invoke(key2CommandsFtx.id, updatedFilteredComponentsNoSignersKey2SamePMT, key2CommandsFtx.groupHashes) as FilteredTransaction
|
val ftxNoLastSigner = ftxConstructor.invoke(key2CommandsFtx.id, updatedFilteredComponentsNoSignersKey2SamePMT, key2CommandsFtx.groupHashes)
|
||||||
// verify() will fail as we didn't change the partial Merkle tree.
|
// verify() will fail as we didn't change the partial Merkle tree.
|
||||||
assertFailsWith<FilteredTransactionVerificationException> { ftxNoLastSigner.verify() }
|
assertFailsWith<FilteredTransactionVerificationException> { ftxNoLastSigner.verify() }
|
||||||
// checkCommandVisibility() will not pass.
|
// checkCommandVisibility() will not pass.
|
||||||
@ -517,7 +518,7 @@ class CompatibleTransactionTests {
|
|||||||
|
|
||||||
// Remove last signer for which there is no pointer from a visible commandData. This is the case of Key2.
|
// Remove last signer for which there is no pointer from a visible commandData. This is the case of Key2.
|
||||||
// Update partial Merkle tree for signers.
|
// Update partial Merkle tree for signers.
|
||||||
val ftxNoLastSignerB = ftxConstructor.invoke(key2CommandsFtx.id, updatedFilteredComponentsNoSignersKey2, key2CommandsFtx.groupHashes) as FilteredTransaction
|
val ftxNoLastSignerB = ftxConstructor.invoke(key2CommandsFtx.id, updatedFilteredComponentsNoSignersKey2, key2CommandsFtx.groupHashes)
|
||||||
// verify() will pass, the transaction is well-formed.
|
// verify() will pass, the transaction is well-formed.
|
||||||
ftxNoLastSignerB.verify()
|
ftxNoLastSignerB.verify()
|
||||||
// But, checkAllComponentsVisible() will not pass.
|
// But, checkAllComponentsVisible() will not pass.
|
||||||
@ -542,14 +543,14 @@ class CompatibleTransactionTests {
|
|||||||
val alterFilteredComponents = listOf(key1CommandsFtx.filteredComponentGroups[0], alterSignerGroup)
|
val alterFilteredComponents = listOf(key1CommandsFtx.filteredComponentGroups[0], alterSignerGroup)
|
||||||
|
|
||||||
// Do not update groupHashes.
|
// Do not update groupHashes.
|
||||||
val ftxAlterSigner = ftxConstructor.invoke(key1CommandsFtx.id, alterFilteredComponents, key1CommandsFtx.groupHashes) as FilteredTransaction
|
val ftxAlterSigner = ftxConstructor.invoke(key1CommandsFtx.id, alterFilteredComponents, key1CommandsFtx.groupHashes)
|
||||||
// Visible components in signers group cannot be verified against their partial Merkle tree.
|
// Visible components in signers group cannot be verified against their partial Merkle tree.
|
||||||
assertFailsWith<FilteredTransactionVerificationException> { ftxAlterSigner.verify() }
|
assertFailsWith<FilteredTransactionVerificationException> { ftxAlterSigner.verify() }
|
||||||
// Also, checkAllComponentsVisible() will not pass (groupHash matching will fail).
|
// Also, checkAllComponentsVisible() will not pass (groupHash matching will fail).
|
||||||
assertFailsWith<ComponentVisibilityException> { ftxAlterSigner.checkCommandVisibility(DUMMY_KEY_1.public) }
|
assertFailsWith<ComponentVisibilityException> { ftxAlterSigner.checkCommandVisibility(DUMMY_KEY_1.public) }
|
||||||
|
|
||||||
// Update groupHashes.
|
// Update groupHashes.
|
||||||
val ftxAlterSignerB = ftxConstructor.invoke(key1CommandsFtx.id, alterFilteredComponents, key1CommandsFtx.groupHashes.subList(0, 6) + alterMTree.hash) as FilteredTransaction
|
val ftxAlterSignerB = ftxConstructor.invoke(key1CommandsFtx.id, alterFilteredComponents, key1CommandsFtx.groupHashes.subList(0, 6) + alterMTree.hash)
|
||||||
// Visible components in signers group cannot be verified against their partial Merkle tree.
|
// Visible components in signers group cannot be verified against their partial Merkle tree.
|
||||||
assertFailsWith<FilteredTransactionVerificationException> { ftxAlterSignerB.verify() }
|
assertFailsWith<FilteredTransactionVerificationException> { ftxAlterSignerB.verify() }
|
||||||
// Also, checkAllComponentsVisible() will not pass (top level Merkle tree cannot be verified against transaction's id).
|
// Also, checkAllComponentsVisible() will not pass (top level Merkle tree cannot be verified against transaction's id).
|
||||||
|
@ -32,7 +32,7 @@ import org.junit.Test
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
|
|
||||||
val TEST_TIMELOCK_ID = "net.corda.core.transactions.TransactionEncumbranceTests\$DummyTimeLock"
|
const val TEST_TIMELOCK_ID = "net.corda.core.transactions.TransactionEncumbranceTests\$DummyTimeLock"
|
||||||
|
|
||||||
class TransactionEncumbranceTests {
|
class TransactionEncumbranceTests {
|
||||||
private companion object {
|
private companion object {
|
||||||
|
@ -476,7 +476,7 @@ public class FlowCookbookJava {
|
|||||||
subFlow(new SendStateAndRefFlow(counterpartySession, dummyStates));
|
subFlow(new SendStateAndRefFlow(counterpartySession, dummyStates));
|
||||||
|
|
||||||
// On the receive side ...
|
// On the receive side ...
|
||||||
List<StateAndRef<DummyState>> resolvedStateAndRef = subFlow(new ReceiveStateAndRefFlow<DummyState>(counterpartySession));
|
List<StateAndRef<DummyState>> resolvedStateAndRef = subFlow(new ReceiveStateAndRefFlow<>(counterpartySession));
|
||||||
// DOCEND 14
|
// DOCEND 14
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -60,7 +60,7 @@ public class CommercialPaper implements Contract {
|
|||||||
requireThat(require -> {
|
requireThat(require -> {
|
||||||
require.using("the paper must have matured", time.isAfter(input.getMaturityDate()));
|
require.using("the paper must have matured", time.isAfter(input.getMaturityDate()));
|
||||||
require.using("the received amount equals the face value", received == input.getFaceValue());
|
require.using("the received amount equals the face value", received == input.getFaceValue());
|
||||||
require.using("the paper must be destroyed", outputs.size() == 0);
|
require.using("the paper must be destroyed", outputs.isEmpty());
|
||||||
require.using("the transaction is signed by the owner of the CP", cmd.getSigners().contains(input.getOwner().getOwningKey()));
|
require.using("the transaction is signed by the owner of the CP", cmd.getSigners().contains(input.getOwner().getOwningKey()));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
@ -153,9 +153,8 @@ object TopupIssuerFlow {
|
|||||||
// now invoke Cash subflow to Move issued assetType to issue requester
|
// now invoke Cash subflow to Move issued assetType to issue requester
|
||||||
progressTracker.currentStep = TRANSFERRING
|
progressTracker.currentStep = TRANSFERRING
|
||||||
val moveCashFlow = CashPaymentFlow(amount, issueTo, anonymous = false)
|
val moveCashFlow = CashPaymentFlow(amount, issueTo, anonymous = false)
|
||||||
val moveTx = subFlow(moveCashFlow)
|
|
||||||
// NOTE: CashFlow PayCash calls FinalityFlow which performs a Broadcast (which stores a local copy of the txn to the ledger)
|
// NOTE: CashFlow PayCash calls FinalityFlow which performs a Broadcast (which stores a local copy of the txn to the ledger)
|
||||||
return moveTx
|
return subFlow(moveCashFlow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user