IRS demo fixes (#782)

* Increase max network map request size so the notary can register
* Suppress oracle service installation errors in non-oracle nodes
* Make demos automatically build capsule jars
This commit is contained in:
Andrzej Cichocki 2017-06-02 16:23:05 +01:00 committed by Katarzyna Streich
parent ddd36b019e
commit fc63848aa4
17 changed files with 64 additions and 43 deletions

View File

@ -11,6 +11,9 @@ import kotlin.annotation.AnnotationTarget.CLASS
* *
* The service class has to implement [net.corda.core.serialization.SerializeAsToken] to ensure correct usage within flows. * The service class has to implement [net.corda.core.serialization.SerializeAsToken] to ensure correct usage within flows.
* (If possible extend [net.corda.core.serialization.SingletonSerializeAsToken] instead as it removes the boilerplate.) * (If possible extend [net.corda.core.serialization.SingletonSerializeAsToken] instead as it removes the boilerplate.)
*
* The annotated class should expose its [ServiceType] via a public static field named `type`, so that the service is
* only loaded in nodes that declare the type in their advertisedServices.
*/ */
// TODO Handle the singleton serialisation of Corda services automatically, removing the need to implement SerializeAsToken // TODO Handle the singleton serialisation of Corda services automatically, removing the need to implement SerializeAsToken
// TODO Currently all nodes which load the plugin will attempt to load the service even if it's not revelant to them. The // TODO Currently all nodes which load the plugin will attempt to load the service even if it's not revelant to them. The

View File

@ -43,8 +43,8 @@ dependencies {
exclude group: "bouncycastle" exclude group: "bouncycastle"
} }
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
} }
mainClassName = "net.corda.docs.ClientRpcTutorialKt" mainClassName = "net.corda.docs.ClientRpcTutorialKt"

View File

@ -268,18 +268,33 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun installCordaServices(scanResult: ScanResult): List<SerializeAsToken> { private fun installCordaServices(scanResult: ScanResult): List<SerializeAsToken> {
return scanResult.getClassesWithAnnotation(SerializeAsToken::class, CordaService::class).mapNotNull { return scanResult.getClassesWithAnnotation(SerializeAsToken::class, CordaService::class).mapNotNull {
try { tryInstallCordaService(it)
installCordaService(it) }
}
private fun <T : SerializeAsToken> tryInstallCordaService(serviceClass: Class<T>): T? {
/** TODO: This mechanism may get replaced by a different one, see comments on [CordaService]. */
val typeField = try {
serviceClass.getField("type")
} catch (e: NoSuchFieldException) {
null
}
if (typeField == null) {
log.warn("${serviceClass.name} does not have a type field, optimistically proceeding with install.")
} else if (info.serviceIdentities(typeField.get(null) as ServiceType).isEmpty()) {
return null
}
return try {
installCordaService(serviceClass)
} catch (e: NoSuchMethodException) { } catch (e: NoSuchMethodException) {
log.error("${it.name}, as a Corda service, must have a constructor with a single parameter " + log.error("${serviceClass.name}, as a Corda service, must have a constructor with a single parameter " +
"of type ${PluginServiceHub::class.java.name}") "of type ${PluginServiceHub::class.java.name}")
null null
} catch (e: Exception) { } catch (e: Exception) {
log.error("Unable to install Corda service ${it.name}", e) log.error("Unable to install Corda service ${serviceClass.name}", e)
null null
} }
} }
}
/** /**
* Use this method to install your Corda services in your tests. This is automatically done by the node when it * Use this method to install your Corda services in your tests. This is automatically done by the node when it

View File

@ -18,6 +18,7 @@ import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.node.services.api.AbstractNodeService import net.corda.node.services.api.AbstractNodeService
import net.corda.node.services.api.ServiceHubInternal import net.corda.node.services.api.ServiceHubInternal
@ -135,10 +136,10 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
val minimumPlatformVersion: Int) : NetworkMapService, AbstractNodeService(services) { val minimumPlatformVersion: Int) : NetworkMapService, AbstractNodeService(services) {
companion object { companion object {
/** /**
* Maximum credible size for a registration request. Generally requests are around 500-600 bytes, so this gives a * Maximum credible size for a registration request. Generally requests are around 2000-6000 bytes, so this gives a
* 10 times overhead. * 10 times overhead.
*/ */
private const val MAX_SIZE_REGISTRATION_REQUEST_BYTES = 5500 private const val MAX_SIZE_REGISTRATION_REQUEST_BYTES = 40000
private val logger = loggerFor<AbstractNetworkMapService>() private val logger = loggerFor<AbstractNetworkMapService>()
} }
@ -232,7 +233,9 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
} }
private fun processRegistrationRequest(request: RegistrationRequest): RegistrationResponse { private fun processRegistrationRequest(request: RegistrationRequest): RegistrationResponse {
if (request.wireReg.raw.size > MAX_SIZE_REGISTRATION_REQUEST_BYTES) { val requestSize = request.wireReg.raw.size
logger.debug { "Received registration request of size: $requestSize" }
if (requestSize > MAX_SIZE_REGISTRATION_REQUEST_BYTES) {
return RegistrationResponse("Request is too big") return RegistrationResponse("Request is too big")
} }

View File

@ -26,8 +26,8 @@ dependencies {
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
// Corda integration dependencies // Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core') compile project(':core')
compile project(':test-utils') compile project(':test-utils')

View File

@ -26,8 +26,8 @@ dependencies {
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
// Corda integration dependencies // Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core') compile project(':core')
compile project(':client:jfx') compile project(':client:jfx')
compile project(':client:rpc') compile project(':client:rpc')

View File

@ -30,8 +30,8 @@ dependencies {
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
// Corda integration dependencies // Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core') compile project(':core')
compile project(':finance') compile project(':finance')
compile project(':webserver') compile project(':webserver')

View File

@ -39,7 +39,7 @@ class IRSDemoTest : IntegrationTestCategory {
systemProperties = mapOf("net.corda.node.cordapp.scan.package" to "net.corda.irs")) systemProperties = mapOf("net.corda.node.cordapp.scan.package" to "net.corda.irs"))
{ {
val (controller, nodeA, nodeB) = Futures.allAsList( val (controller, nodeA, nodeB) = Futures.allAsList(
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.type))), startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.Oracle.type))),
startNode(DUMMY_BANK_A.name, rpcUsers = listOf(rpcUser)), startNode(DUMMY_BANK_A.name, rpcUsers = listOf(rpcUser)),
startNode(DUMMY_BANK_B.name) startNode(DUMMY_BANK_B.name)
).getOrThrow() ).getOrThrow()

View File

@ -17,7 +17,7 @@ import net.corda.node.services.transactions.SimpleNotaryService
fun main(args: Array<String>) { fun main(args: Array<String>) {
driver(dsl = { driver(dsl = {
val (controller, nodeA, nodeB) = Futures.allAsList( val (controller, nodeA, nodeB) = Futures.allAsList(
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.type))), startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.Oracle.type))),
startNode(DUMMY_BANK_A.name), startNode(DUMMY_BANK_A.name),
startNode(DUMMY_BANK_B.name) startNode(DUMMY_BANK_B.name)
).getOrThrow() ).getOrThrow()

View File

@ -49,8 +49,6 @@ import kotlin.collections.set
* for signing. * for signing.
*/ */
object NodeInterestRates { object NodeInterestRates {
val type = ServiceType.corda.getSubType("interest_rates")
// DOCSTART 2 // DOCSTART 2
@InitiatedBy(RatesFixFlow.FixSignFlow::class) @InitiatedBy(RatesFixFlow.FixSignFlow::class)
class FixSignHandler(val otherParty: Party) : FlowLogic<Unit>() { class FixSignHandler(val otherParty: Party) : FlowLogic<Unit>() {
@ -95,6 +93,11 @@ object NodeInterestRates {
) )
// DOCEND 3 // DOCEND 3
companion object {
@JvmField
val type = ServiceType.corda.getSubType("interest_rates")
}
private object Table : JDBCHashedTable("demo_interest_rate_fixes") { private object Table : JDBCHashedTable("demo_interest_rate_fixes") {
val name = varchar("index_name", length = 255) val name = varchar("index_name", length = 255)
val forDay = localDate("for_day") val forDay = localDate("for_day")

View File

@ -10,6 +10,7 @@ import net.corda.core.identity.Party
import net.corda.core.node.services.ServiceType import net.corda.core.node.services.ServiceType
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.irs.api.NodeInterestRates
import net.corda.irs.flows.FixingFlow import net.corda.irs.flows.FixingFlow
import net.corda.irs.utilities.suggestInterestRateAnnouncementTimeWindow import net.corda.irs.utilities.suggestInterestRateAnnouncementTimeWindow
import org.apache.commons.jexl3.JexlBuilder import org.apache.commons.jexl3.JexlBuilder
@ -190,10 +191,6 @@ class FloatingRatePaymentEvent(date: LocalDate,
class InterestRateSwap : Contract { class InterestRateSwap : Contract {
override val legalContractReference = SecureHash.sha256("is_this_the_text_of_the_contract ? TBD") override val legalContractReference = SecureHash.sha256("is_this_the_text_of_the_contract ? TBD")
companion object {
val oracleType = ServiceType.corda.getSubType("interest_rates")
}
/** /**
* This Common area contains all the information that is not leg specific. * This Common area contains all the information that is not leg specific.
*/ */
@ -665,7 +662,7 @@ class InterestRateSwap : Contract {
override val contract = IRS_PROGRAM_ID override val contract = IRS_PROGRAM_ID
override val oracleType: ServiceType override val oracleType: ServiceType
get() = InterestRateSwap.oracleType get() = NodeInterestRates.Oracle.type
override val ref = common.tradeID override val ref = common.tradeID

View File

@ -121,7 +121,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): MockNetwork.MockNode {
require(advertisedServices.containsType(NodeInterestRates.type)) require(advertisedServices.containsType(NodeInterestRates.Oracle.type))
val cfg = TestNodeConfiguration( val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
myLegalName = RATES_SERVICE_NAME, myLegalName = RATES_SERVICE_NAME,
@ -166,7 +166,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
= network.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode = network.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode
val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode) val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
val ratesOracle: SimulatedNode val ratesOracle: SimulatedNode
= network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.type)) as SimulatedNode = network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type)) as SimulatedNode
// All nodes must be in one of these two lists for the purposes of the visualiser tool. // All nodes must be in one of these two lists for the purposes of the visualiser tool.
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap) val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)

View File

@ -209,7 +209,7 @@ class NodeInterestRatesTest {
fun `network tearoff`() { fun `network tearoff`() {
val net = MockNetwork() val net = MockNetwork()
val n1 = net.createNotaryNode() val n1 = net.createNotaryNode()
val n2 = net.createNode(n1.info.address, advertisedServices = ServiceInfo(NodeInterestRates.type)) val n2 = net.createNode(n1.info.address, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type))
n2.registerInitiatedFlow(NodeInterestRates.FixQueryHandler::class.java) n2.registerInitiatedFlow(NodeInterestRates.FixQueryHandler::class.java)
n2.registerInitiatedFlow(NodeInterestRates.FixSignHandler::class.java) n2.registerInitiatedFlow(NodeInterestRates.FixSignHandler::class.java)
n2.database.transaction { n2.database.transaction {
@ -217,7 +217,7 @@ class NodeInterestRatesTest {
} }
val tx = TransactionType.General.Builder(null) val tx = TransactionType.General.Builder(null)
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val oracle = n2.info.serviceIdentities(NodeInterestRates.type).first() val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first()
val flow = FilteredRatesFlow(tx, oracle, fixOf, "0.675".bd, "0.1".bd) val flow = FilteredRatesFlow(tx, oracle, fixOf, "0.675".bd, "0.1".bd)
LogHelper.setLevel("rates") LogHelper.setLevel("rates")
net.runNetwork() net.runNetwork()

View File

@ -12,8 +12,8 @@ dependencies {
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
// Corda integration dependencies // Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core') compile project(':core')
compile project(':finance') compile project(':finance')
testCompile project(':test-utils') testCompile project(':test-utils')

View File

@ -18,8 +18,8 @@ dependencies {
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
// Corda integration dependencies // Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core') compile project(':core')
compile project(':client:jfx') compile project(':client:jfx')
compile project(':client:rpc') compile project(':client:rpc')

View File

@ -31,8 +31,8 @@ dependencies {
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
// Corda integration dependencies // Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core') compile project(':core')
compile project(':node') compile project(':node')
compile project(':webserver') compile project(':webserver')

View File

@ -27,8 +27,8 @@ dependencies {
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
// Corda integration dependencies // Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts') compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core') compile project(':core')
compile project(':finance') compile project(':finance')
compile project(':test-utils') compile project(':test-utils')